merged in master and resolved conflict in Salt provisioner docs

This commit is contained in:
Tim O'Guin 2015-06-01 10:07:28 -05:00
commit 0b24866537
128 changed files with 2648 additions and 213 deletions

1
.gitignore vendored
View File

@ -16,6 +16,7 @@ pkg/*
tags tags
/Gemfile.lock /Gemfile.lock
test/tmp/ test/tmp/
vendor/
# Documentation # Documentation
_site/* _site/*

View File

@ -1,13 +1,21 @@
language: ruby language: ruby
before_install: before_install:
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq -y bsdtar - sudo apt-get install -qq -y bsdtar
- rvm @global do gem uninstall bundler --all --executables - rvm @global do gem uninstall bundler --all --executables
- gem uninstall bundler --all --executables - gem uninstall bundler --all --executables
- gem install bundler --version '< 1.7.0' - gem install bundler --version '< 1.7.0'
rvm: rvm:
- 2.0.0 - 2.0.0
branches:
only:
- master
env: env:
global: global:
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
script: rake test:unit script: rake test:unit

View File

@ -2,44 +2,91 @@
IMPROVEMENTS: IMPROVEMENTS:
- guests/darwin: Support inserting generated key. [GH-5204] - core: add password authentication to rdp_info hash [GH-4726]
- guests/fedora: Support Fedora 21. [GH-5277] - core: improve error message when packaging fails [GH-5399]
- guests/redhat: Support Scientific Linux 7 [GH-5303] - core: improve message when adding a box from a file path [GH-5395]
- guests/solaris,solaris11: Support inserting generated key. [GH-5182] - core: add support for network gateways [GH-5721]
- core: allow redirecting stdout and stderr in the UI [GH-5433]
- core: update version of winrm-fs to 0.2.0 [GH-5738]
- core: add option to enabled trusted http(s) redirects [GH-4422]
- core: capture additional information such as line numbers during
Vagrantfile loading [GH-4711, GH-5769]
- guests/darwin: support inserting generated key [GH-5204]
- guests/darwin: support mounting SMB shares [GH-5750]
- guests/fedora: support Fedora 21 [GH-5277]
- guests/fedora: add capabilities for nfs and flavor [GH-5770, GH-4847]
- guests/linux: specify user's domain as separate parameter [GH-3620, GH-5512]
- guests/redhat: support Scientific Linux 7 [GH-5303]
- guests/photon: initial support [GH-5612]
- guests/solaris,solaris11: support inserting generated key [GH-5182]
[GH-5290] [GH-5290]
- providers/virtualbox: regexp supported for bridge configuration. [GH-5320] - provisioners/chef: add capability for checking if Chef is installed on Windows [GH-5669]
- provisioners/puppet: add support for Puppet 4 and configuration options [GH-5601]
- provisioners/puppet: add support for `synced_folder_args` in apply [GH-5359]
- provisioners/salt: add configurable `config_dir` [GH-3138]
- provisioners/salt: add support for masterless configuration [GH-3235]
- provisioners/salt: provider path to missing file in errors [GH-5637]
- provisioners/salt: add ability to run salt orchestrations [GH-4371]
- provisioners/salt: update to 2014.7.1 [GH-4152, GH-5437]
- provisioners/shell: add :name attribute to shell provisioner [GH-5607]
- providers/hyperv: select a Hyper-V switch based on a network_name [GH-5207]
- providers/hyperv: allow configuring VladID [GH-5539]
- providers/virtualbox: regexp supported for bridge configuration [GH-5320]
- providers/virtualbox: add support for 5.0 [GH-5647]
- providers/virtualbox: handle a list of bridged NICs [GH-5691]
- synced_folders/rsync: allow showing rsync output in debug mode [GH-4867]
BUG FIXES: BUG FIXES:
- core: push configurations are validated with global configs [GH-5130] - core: push configurations are validated with global configs [GH-5130]
- core: remove executable permissions on internal file [GH-5220] - core: remove executable permissions on internal file [GH-5220]
- core: check name and version in `has_plugin?` [GH-5218] - core: check name and version in `has_plugin?` [GH-5218]
- core: do not create duplicates when defining two private network addresses [GH-5325]
- core: update ssh to check for Plink [GH-5604]
- core: do not report plugins as installed when plugins are disabled [GH-5698, GH-5430]
- core: Only take files when packaging a box to avoid duplicates [GH-5658, GH-5657]
- core: escape curl urls and authentication [GH-5677]
- core/cli: fix box checksum validation [GH-4665, GH-5221] - core/cli: fix box checksum validation [GH-4665, GH-5221]
- core/windows: allow Windows UNC paths to allow more than 256
characters [GH-4815]
- communicators/winrm: improve error handling significantly and improve - communicators/winrm: improve error handling significantly and improve
the error messages shown to be more human-friendly. [GH-4943] the error messages shown to be more human-friendly. [GH-4943]
- hosts/nfs: allow colons (`:`) in NFS IDs [GH-5222] - hosts/nfs: allow colons (`:`) in NFS IDs [GH-5222]
- guests/darwin: remove dots from LocalHostName [GH-5558]
- guests/debian: Halt works properly on Debian 8. [GH-5369] - guests/debian: Halt works properly on Debian 8. [GH-5369]
- guests/fedora: recognize future fedora releases [GH-5730]
- guests/fedora: reload iface connection by NetworkManager [GH-5709]
- guests/fedora: do not use biosdevname if it is not installed [GH-5707]
- guests/freebsd: provide an argument to the backup file [GH-5516, GH-5517]
- guests/funtoo: fix incorrect path in configure networks [GH-4812] - guests/funtoo: fix incorrect path in configure networks [GH-4812]
- guests/tinycore: fix change hostname functionality [GH-5623]
- guests/windows: Create rsync folder prior to rsync-ing. [GH-5282] - guests/windows: Create rsync folder prior to rsync-ing. [GH-5282]
- guests/windows: Changing hostname requires reboot again since - guests/windows: Changing hostname requires reboot again since
the non-reboot code path was crashing Windows server. [GH-5261] the non-reboot code path was crashing Windows server. [GH-5261]
- guests/windows: ignore virtual NICs [GH-5478]
- hosts/windows: More accurately get host IP address in VPNs. [GH-5349] - hosts/windows: More accurately get host IP address in VPNs. [GH-5349]
- plugins/login: allow users to login with a token [GH-5145] - plugins/login: allow users to login with a token [GH-5145]
- providers/docker: Build image from `/var/lib/docker` for more disk - providers/docker: Build image from `/var/lib/docker` for more disk
space on some systems. [GH-5302] space on some systems. [GH-5302]
- providers/hyperv: allow users to configure memory, cpu count, and vmname [GH-5183] - providers/hyperv: allow users to configure memory, cpu count, and vmname [GH-5183]
- providers/hyperv: import respects secure boot. [GH-5209] - providers/hyperv: import respects secure boot. [GH-5209]
- providers/hyperv: only set EFI secure boot for gen 2 machines [GH-5538]
- providers/virtualbox: read netmask from dhcpservers [GH-5233] - providers/virtualbox: read netmask from dhcpservers [GH-5233]
- providers/virtualbox: Fix exception when VirtualBox version is empty. [GH-5308] - providers/virtualbox: Fix exception when VirtualBox version is empty. [GH-5308]
- provisioners/ansible: fix SSH settings to support more than 5 ssh keys [GH-5017] - provisioners/ansible: fix SSH settings to support more than 5 ssh keys [GH-5017]
- provisioners/ansible: increase ansible connection timeout to 30 seconds [GH-5018] - provisioners/ansible: increase ansible connection timeout to 30 seconds [GH-5018]
- provisioners/ansible: disable color if Vagrant is not colored [GH-5531, GH-5532]
- provisioners/docker: use `service` to restart Docker instad of upstart [GH-5245, GH-5577]
- provisioners/docker: Only add docker user to group if exists. [GH-5315] - provisioners/docker: Only add docker user to group if exists. [GH-5315]
- provisioners/docker: Use https for repo [GH-5749]
- provisioners/chef: Use `command -v` to check for binary instead of - provisioners/chef: Use `command -v` to check for binary instead of
`which` since that doesn't exist on some systems. [GH-5170] `which` since that doesn't exist on some systems. [GH-5170]
- provisioners/chef-zero: support more chef-zero/local mode attributes [GH-5339] - provisioners/chef-zero: support more chef-zero/local mode attributes [GH-5339]
- provisioners/docker: use docker.com instead of docker.io [GH-5216] - provisioners/docker: use docker.com instead of docker.io [GH-5216]
- pushes/atlas: send additional box metadata [GH-5283] - pushes/atlas: send additional box metadata [GH-5283]
- synced\_folders/rsync: Add `IdentitiesOnly=yes` to the rsync command. [GH-5175] - pushes/ftp: improve check for remote directory existence [GH-5549]
- synced\_folders/rsync: add `IdentitiesOnly=yes` to the rsync command. [GH-5175]
- virtualbox/config: fix misleading error message for private_network [GH-5536, GH-5418]
## 1.7.2 (January 6, 2015) ## 1.7.2 (January 6, 2015)
@ -133,7 +180,7 @@ IMPROVEMENTS:
- core: `has_plugin?` function now takes a second argument which is a - core: `has_plugin?` function now takes a second argument which is a
version constraint requirement. [GH-4650] version constraint requirement. [GH-4650]
- core: ".vagrantplugins" file in the same file as your Vagrantfile - core: ".vagrantplugins" file in the same folder as your Vagrantfile
will be loaded for defining inline plugins. [GH-3775] will be loaded for defining inline plugins. [GH-3775]
- commands/plugin: Plugin list machine-readable output contains the plugin - commands/plugin: Plugin list machine-readable output contains the plugin
name as the target for versions and other info. [GH-4506] name as the target for versions and other info. [GH-4506]

8
Vagrantfile vendored
View File

@ -5,6 +5,8 @@
Vagrant.configure("2") do |config| Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise64" config.vm.box = "hashicorp/precise64"
config.vm.hostname = "vagrant"
config.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
["vmware_fusion", "vmware_workstation", "virtualbox"].each do |provider| ["vmware_fusion", "vmware_workstation", "virtualbox"].each do |provider|
config.vm.provider provider do |v, override| config.vm.provider provider do |v, override|
@ -24,6 +26,7 @@ Vagrant.configure("2") do |config|
end end
$shell = <<-CONTENTS $shell = <<-CONTENTS
export DEBIAN_FRONTEND=noninteractive
MARKER_FILE="/usr/local/etc/vagrant_provision_marker" MARKER_FILE="/usr/local/etc/vagrant_provision_marker"
# Only provision once # Only provision once
@ -37,8 +40,11 @@ apt-get update
# Install basic dependencies # Install basic dependencies
apt-get install -y build-essential bsdtar curl apt-get install -y build-essential bsdtar curl
# Import the mpapis public key to verify downloaded releases
su -l -c 'curl -sSL https://rvm.io/mpapis.asc | gpg -q --import -' vagrant
# Install RVM # Install RVM
su -l -c 'curl -L https://get.rvm.io | bash -s stable' vagrant su -l -c 'curl -sL https://get.rvm.io | bash -s stable' vagrant
# Add the vagrant user to the RVM group # Add the vagrant user to the RVM group
#usermod -a -G rvm vagrant #usermod -a -G rvm vagrant

View File

@ -70,8 +70,13 @@ _vagrant() {
return 0 return 0
;; ;;
"up") "up")
vagrant_state_file=$(__vagrantinvestigate) || return 1
if [[ -d $vagrant_state_file ]]
then
local vm_list=$(find $vagrant_state_file/machines -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
fi
local up_commands="--no-provision" local up_commands="--no-provision"
COMPREPLY=($(compgen -W "${up_commands}" -- ${cur})) COMPREPLY=($(compgen -W "${up_commands} ${vm_list}" -- ${cur}))
return 0 return 0
;; ;;
"ssh"|"provision"|"reload"|"halt"|"suspend"|"resume"|"ssh-config") "ssh"|"provision"|"reload"|"halt"|"suspend"|"resume"|"ssh-config")
@ -107,8 +112,19 @@ _vagrant() {
if [ $COMP_CWORD == 3 ] if [ $COMP_CWORD == 3 ]
then then
action="${COMP_WORDS[COMP_CWORD-2]}" action="${COMP_WORDS[COMP_CWORD-2]}"
if [ $action == 'box' ] case "$action" in
"up")
if [ "$prev" == "--no-provision" ]
then then
if [[ -d $vagrant_state_file ]]
then
local vm_list=$(find $vagrant_state_file/machines -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
fi
COMPREPLY=($(compgen -W "${vm_list}" -- ${cur}))
return 0
fi
;;
"box")
case "$prev" in case "$prev" in
"remove"|"repackage") "remove"|"repackage")
local box_list=$(find "${VAGRANT_HOME:-${HOME}/.vagrant.d}/boxes" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) local box_list=$(find "${VAGRANT_HOME:-${HOME}/.vagrant.d}/boxes" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;)
@ -118,7 +134,10 @@ _vagrant() {
*) *)
;; ;;
esac esac
fi ;;
*)
;;
esac
fi fi
} }

View File

@ -139,10 +139,12 @@ module Vagrant
Config.run(version, &block) Config.run(version, &block)
end end
# This checks if a plugin with the given name is installed. This can # This checks if a plugin with the given name is available (installed
# be used from the Vagrantfile to easily branch based on plugin # and enabled). This can be used from the Vagrantfile to easily branch
# availability. # based on plugin availability.
def self.has_plugin?(name, version=nil) def self.has_plugin?(name, version=nil)
return false unless Vagrant.plugins_enabled?
if !version if !version
# We check the plugin names first because those are cheaper to check # We check the plugin names first because those are cheaper to check
return true if plugin("2").manager.registered.any? { |p| p.name == name } return true if plugin("2").manager.registered.any? { |p| p.name == name }

View File

@ -404,6 +404,7 @@ module Vagrant
downloader_options[:client_cert] = env[:box_download_client_cert] downloader_options[:client_cert] = env[:box_download_client_cert]
downloader_options[:headers] = ["Accept: application/json"] if opts[:json] downloader_options[:headers] = ["Accept: application/json"] if opts[:json]
downloader_options[:ui] = env[:ui] if opts[:ui] downloader_options[:ui] = env[:ui] if opts[:ui]
downloader_options[:location_trusted] = env[:box_download_location_trusted]
Util::Downloader.new(url, temp_path, downloader_options) Util::Downloader.new(url, temp_path, downloader_options)
end end
@ -420,8 +421,15 @@ module Vagrant
show_url = opts[:show_url] show_url = opts[:show_url]
show_url ||= url show_url ||= url
translation = "vagrant.box_downloading"
# Adjust status message when 'downloading' a local box.
if show_url.start_with?("file://")
translation = "vagrant.box_unpacking"
end
env[:ui].detail(I18n.t( env[:ui].detail(I18n.t(
"vagrant.box_downloading", translation,
url: show_url)) url: show_url))
if File.file?(d.destination) if File.file?(d.destination)
env[:ui].info(I18n.t("vagrant.actions.box.download.resuming")) env[:ui].info(I18n.t("vagrant.actions.box.download.resuming"))

View File

@ -66,6 +66,7 @@ module Vagrant
box_download_insecure = machine.config.vm.box_download_insecure box_download_insecure = machine.config.vm.box_download_insecure
box_download_checksum_type = machine.config.vm.box_download_checksum_type box_download_checksum_type = machine.config.vm.box_download_checksum_type
box_download_checksum = machine.config.vm.box_download_checksum box_download_checksum = machine.config.vm.box_download_checksum
box_download_location_trusted = machine.config.vm.box_download_location_trusted
box_formats = machine.provider_options[:box_format] || box_formats = machine.provider_options[:box_format] ||
machine.provider_name machine.provider_name
@ -90,6 +91,7 @@ module Vagrant
box_download_insecure: box_download_insecure, box_download_insecure: box_download_insecure,
box_checksum_type: box_download_checksum_type, box_checksum_type: box_download_checksum_type,
box_checksum: box_download_checksum, box_checksum: box_download_checksum,
box_download_location_trusted: box_download_location_trusted,
})) }))
rescue Errors::BoxAlreadyExists rescue Errors::BoxAlreadyExists
# Just ignore this, since it means the next part will succeed! # Just ignore this, since it means the next part will succeed!

View File

@ -29,9 +29,10 @@ module Vagrant
def call(env) def call(env)
@env = env @env = env
file_name = File.basename(@env["package.output"].to_s)
raise Errors::PackageOutputDirectory if File.directory?(tar_path) raise Errors::PackageOutputDirectory if File.directory?(tar_path)
raise Errors::PackageOutputExists if File.exist?(tar_path) raise Errors::PackageOutputExists, file_name:file_name if File.exist?(tar_path)
raise Errors::PackageRequiresDirectory if !env["package.directory"] || raise Errors::PackageRequiresDirectory if !env["package.directory"] ||
!File.directory?(env["package.directory"]) !File.directory?(env["package.directory"])

View File

@ -173,7 +173,7 @@ module Vagrant
Util::SafeChdir.safe_chdir(@directory) do Util::SafeChdir.safe_chdir(@directory) do
# Find all the files in our current directory and tar it up! # Find all the files in our current directory and tar it up!
files = Dir.glob(File.join(".", "**", "*")) files = Dir.glob(File.join(".", "**", "*")).select { |f| File.file?(f) }
# Package! # Package!
Util::Subprocess.execute("bsdtar", "-czf", path.to_s, *files) Util::Subprocess.execute("bsdtar", "-czf", path.to_s, *files)

View File

@ -209,9 +209,16 @@ module Vagrant
@logger.error("Vagrantfile load error: #{e.message}") @logger.error("Vagrantfile load error: #{e.message}")
@logger.error(e.backtrace.join("\n")) @logger.error(e.backtrace.join("\n"))
line = "(unknown)"
if e.backtrace && e.backtrace[0]
line = e.backtrace[0].split(":")[1]
end
# Report the generic exception # Report the generic exception
raise Errors::VagrantfileLoadError, raise Errors::VagrantfileLoadError,
path: path, path: path,
line: line,
exception_class: e.class,
message: e.message message: e.message
end end
end end

View File

@ -316,6 +316,10 @@ module Vagrant
error_key(:corrupt_machine_index) error_key(:corrupt_machine_index)
end end
class DarwinMountFailed < VagrantError
error_key(:darwin_mount_failed)
end
class DarwinNFSMountFailed < VagrantError class DarwinNFSMountFailed < VagrantError
error_key(:darwin_nfs_mount_failed) error_key(:darwin_nfs_mount_failed)
end end

View File

@ -21,9 +21,22 @@ module Vagrant
# specific. See the implementation for more docs. # specific. See the implementation for more docs.
attr_accessor :opts attr_accessor :opts
# @return [IO] UI input. Defaults to `$stdin`.
attr_accessor :stdin
# @return [IO] UI output. Defaults to `$stdout`.
attr_accessor :stdout
# @return [IO] UI error output. Defaults to `$stderr`.
attr_accessor :stderr
def initialize def initialize
@logger = Log4r::Logger.new("vagrant::ui::interface") @logger = Log4r::Logger.new("vagrant::ui::interface")
@opts = {} @opts = {}
@stdin = $stdin
@stdout = $stdout
@stderr = $stderr
end end
def initialize_copy(original) def initialize_copy(original)
@ -132,7 +145,7 @@ module Vagrant
super(message) super(message)
# We can't ask questions when the output isn't a TTY. # We can't ask questions when the output isn't a TTY.
raise Errors::UIExpectsTTY if !$stdin.tty? && !Vagrant::Util::Platform.cygwin? raise Errors::UIExpectsTTY if !@stdin.tty? && !Vagrant::Util::Platform.cygwin?
# Setup the options so that the new line is suppressed # Setup the options so that the new line is suppressed
opts ||= {} opts ||= {}
@ -144,11 +157,11 @@ module Vagrant
say(:info, message, opts) say(:info, message, opts)
input = nil input = nil
if opts[:echo] if opts[:echo] || !@stdin.respond_to?(:noecho)
input = $stdin.gets input = @stdin.gets
else else
begin begin
input = $stdin.noecho(&:gets) input = @stdin.noecho(&:gets)
# Output a newline because without echo, the newline isn't # Output a newline because without echo, the newline isn't
# echoed either. # echoed either.
@ -206,7 +219,7 @@ module Vagrant
# Determine the proper IO channel to send this message # Determine the proper IO channel to send this message
# to based on the type of the message # to based on the type of the message
channel = type == :error || opts[:channel] == :error ? $stderr : $stdout channel = type == :error || opts[:channel] == :error ? @stderr : @stdout
# Output! We wrap this in a lock so that it safely outputs only # Output! We wrap this in a lock so that it safely outputs only
# one line at a time. We wrap this in a thread because as of Ruby 2.0 # one line at a time. We wrap this in a thread because as of Ruby 2.0

View File

@ -27,10 +27,10 @@ module Vagrant
@destination = destination.to_s @destination = destination.to_s
begin begin
url = URI.parse(@source) url = URI.parse(URI.escape(@source))
if url.scheme && url.scheme.start_with?("http") && url.user if url.scheme && url.scheme.start_with?("http") && url.user
auth = "#{url.user}" auth = "#{URI.unescape(url.user)}"
auth += ":#{url.password}" if url.password auth += ":#{URI.unescape(url.password)}" if url.password
url.user = nil url.user = nil
url.password = nil url.password = nil
options[:auth] ||= auth options[:auth] ||= auth
@ -49,6 +49,7 @@ module Vagrant
@insecure = options[:insecure] @insecure = options[:insecure]
@ui = options[:ui] @ui = options[:ui]
@client_cert = options[:client_cert] @client_cert = options[:client_cert]
@location_trusted = options[:location_trusted]
end end
# This executes the actual download, downloading the source file # This executes the actual download, downloading the source file
@ -224,6 +225,7 @@ module Vagrant
options << "--insecure" if @insecure options << "--insecure" if @insecure
options << "--cert" << @client_cert if @client_cert options << "--cert" << @client_cert if @client_cert
options << "-u" << @auth if @auth options << "-u" << @auth if @auth
options << "--location-trusted" if @location_trusted
if @headers if @headers
Array(@headers).each do |header| Array(@headers).each do |header|

View File

@ -144,6 +144,13 @@ module Vagrant
path path
end end
# Converts a given path to UNC format by adding a prefix and converting slashes.
# @param [String] path Path to convert to UNC for Windows
# @return [String]
def windows_unc_path(path)
"\\\\?\\" + path.gsub("/", "\\")
end
# Returns a boolean noting whether the terminal supports color. # Returns a boolean noting whether the terminal supports color.
# output. # output.
def terminal_supports_colors? def terminal_supports_colors?

View File

@ -83,7 +83,7 @@ module Vagrant
# underneath the covers. In this case, we tell the user. # underneath the covers. In this case, we tell the user.
if Platform.windows? if Platform.windows?
r = Subprocess.execute(ssh_path) r = Subprocess.execute(ssh_path)
if r.stdout.include?("PuTTY Link") if r.stdout.include?("PuTTY Link") || r.stdout.include?("Plink: command-line connection utility")
raise Errors::SSHIsPuttyLink, raise Errors::SSHIsPuttyLink,
host: ssh_info[:host], host: ssh_info[:host],
port: ssh_info[:port], port: ssh_info[:port],

View File

@ -38,6 +38,10 @@ module VagrantPlugins
options[:client_cert] = c options[:client_cert] = c
end end
o.on("--location-trusted", "Trust 'Location' header from HTTP redirects and use the same credentials for subsequent urls as for the initial one") do |l|
options[:location_trusted] = l
end
o.on("--provider PROVIDER", String, "Provider the box should satisfy") do |p| o.on("--provider PROVIDER", String, "Provider the box should satisfy") do |p|
options[:provider] = p options[:provider] = p
end end
@ -95,6 +99,7 @@ module VagrantPlugins
box_download_ca_path: options[:ca_path], box_download_ca_path: options[:ca_path],
box_download_client_cert: options[:client_cert], box_download_client_cert: options[:client_cert],
box_download_insecure: options[:insecure], box_download_insecure: options[:insecure],
box_download_location_trusted: options[:location_trusted],
ui: Vagrant::UI::Prefixed.new(@env.ui, "box"), ui: Vagrant::UI::Prefixed.new(@env.ui, "box"),
}) })

View File

@ -70,6 +70,14 @@ module VagrantPlugins
rdp_info[:username] = username rdp_info[:username] = username
end end
if !rdp_info[:password]
password = ssh_info[:password]
if machine.config.vm.communicator == :winrm
password = machine.config.winrm.password
end
rdp_info[:password] = password
end
rdp_info[:host] ||= ssh_info[:host] rdp_info[:host] ||= ssh_info[:host]
rdp_info[:port] ||= machine.config.rdp.port rdp_info[:port] ||= machine.config.rdp.port

View File

@ -434,6 +434,21 @@ module VagrantPlugins
return yield connection if block_given? return yield connection if block_given?
end end
# The shell wrapper command used in shell_execute defined by
# the sudo and shell options.
def shell_cmd(opts)
sudo = opts[:sudo]
shell = opts[:shell]
# Determine the shell to execute. Prefer the explicitly passed in shell
# over the default configured shell. If we are using `sudo` then we
# need to wrap the shell in a `sudo` call.
cmd = @machine.config.ssh.shell
cmd = shell if shell
cmd = "sudo -E -H #{cmd}" if sudo
cmd
end
# Executes the command on an SSH connection within a login shell. # Executes the command on an SSH connection within a login shell.
def shell_execute(connection, command, **opts) def shell_execute(connection, command, **opts)
opts = { opts = {
@ -442,18 +457,10 @@ module VagrantPlugins
}.merge(opts) }.merge(opts)
sudo = opts[:sudo] sudo = opts[:sudo]
shell = opts[:shell]
@logger.info("Execute: #{command} (sudo=#{sudo.inspect})") @logger.info("Execute: #{command} (sudo=#{sudo.inspect})")
exit_status = nil exit_status = nil
# Determine the shell to execute. Prefer the explicitly passed in shell
# over the default configured shell. If we are using `sudo` then we
# need to wrap the shell in a `sudo` call.
shell_cmd = @machine.config.ssh.shell
shell_cmd = shell if shell
shell_cmd = "sudo -E -H #{shell_cmd}" if sudo
# These variables are used to scrub PTY output if we're in a PTY # These variables are used to scrub PTY output if we're in a PTY
pty = false pty = false
pty_stdout = "" pty_stdout = ""
@ -472,7 +479,7 @@ module VagrantPlugins
end end
end end
ch.exec(shell_cmd) do |ch2, _| ch.exec(shell_cmd(opts)) do |ch2, _|
# Setup the channel callbacks so we can get data and exit status # Setup the channel callbacks so we can get data and exit status
ch2.on_data do |ch3, data| ch2.on_data do |ch3, data|
# Filter out the clear screen command # Filter out the clear screen command

View File

@ -27,7 +27,7 @@ $task_xml = @'
<StartWhenAvailable>false</StartWhenAvailable> <StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings> <IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd> <StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle> <RestartOnIdle>false</RestartOnIdle>
</IdleSettings> </IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand> <AllowStartOnDemand>true</AllowStartOnDemand>

View File

@ -6,7 +6,9 @@ module VagrantPlugins
if !machine.communicate.test("hostname -f | grep '^#{name}$' || hostname -s | grep '^#{name}$'") if !machine.communicate.test("hostname -f | grep '^#{name}$' || hostname -s | grep '^#{name}$'")
machine.communicate.sudo("scutil --set ComputerName #{name}") machine.communicate.sudo("scutil --set ComputerName #{name}")
machine.communicate.sudo("scutil --set HostName #{name}") machine.communicate.sudo("scutil --set HostName #{name}")
machine.communicate.sudo("scutil --set LocalHostName #{name}") # LocalHostName shouldn't contain dots.
# It is used by Bonjour and visible through file sharing services.
machine.communicate.sudo("scutil --set LocalHostName #{name.gsub(/\.+/, '')}")
machine.communicate.sudo("hostname #{name}") machine.communicate.sudo("hostname #{name}")
end end
end end

View File

@ -0,0 +1,20 @@
module VagrantPlugins
module GuestDarwin
module Cap
module ChooseAddressableIPAddr
def self.choose_addressable_ip_addr(machine, possible)
machine.communicate.tap do |comm|
possible.each do |ip|
command = "ping -c1 -t1 #{ip}"
if comm.test(command)
return ip
end
end
end
nil
end
end
end
end
end

View File

@ -0,0 +1,37 @@
require "vagrant/util/retryable"
require "shellwords"
module VagrantPlugins
module GuestDarwin
module Cap
class MountSMBSharedFolder
extend Vagrant::Util::Retryable
def self.mount_smb_shared_folder(machine, name, guestpath, options)
expanded_guest_path = machine.guest.capability(:shell_expand_guest_path, guestpath)
mount_point_owner = options[:owner];
if mount_point_owner
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
machine.communicate.sudo("chown #{mount_point_owner} #{expanded_guest_path}")
else
# fallback to assumption that user has permission
# to create the specified mountpoint
machine.communicate.execute("mkdir -p #{expanded_guest_path}")
end
smb_password = Shellwords.shellescape(options[:smb_password])
mount_options = options[:mount_options];
mount_command = "mount -t smbfs " +
(mount_options ? "-o '#{mount_options.join(",")}' " : "") +
"'//#{options[:smb_username]}:#{smb_password}@#{options[:smb_host]}/#{name}' " +
"#{expanded_guest_path}"
retryable(on: Vagrant::Errors::DarwinMountFailed, tries: 10, sleep: 2) do
machine.communicate.execute(
mount_command,
error_class: Vagrant::Errors::DarwinMountFailed)
end
end
end
end
end
end

View File

@ -16,6 +16,11 @@ module VagrantPlugins
Cap::ChangeHostName Cap::ChangeHostName
end end
guest_capability("darwin", "choose_addressable_ip_addr") do
require_relative "cap/choose_addressable_ip_addr"
Cap::ChooseAddressableIPAddr
end
guest_capability("darwin", "configure_networks") do guest_capability("darwin", "configure_networks") do
require_relative "cap/configure_networks" require_relative "cap/configure_networks"
Cap::ConfigureNetworks Cap::ConfigureNetworks
@ -36,6 +41,11 @@ module VagrantPlugins
Cap::MountNFSFolder Cap::MountNFSFolder
end end
guest_capability("darwin", "mount_smb_shared_folder") do
require_relative "cap/mount_smb_shared_folder"
Cap::MountSMBSharedFolder
end
guest_capability("darwin", "mount_vmware_shared_folder") do guest_capability("darwin", "mount_vmware_shared_folder") do
require_relative "cap/mount_vmware_shared_folder" require_relative "cap/mount_vmware_shared_folder"
Cap::MountVmwareSharedFolder Cap::MountVmwareSharedFolder

View File

@ -14,7 +14,7 @@ module VagrantPlugins
# First, remove any previous network modifications # First, remove any previous network modifications
# from the interface file. # from the interface file.
comm.sudo("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre") comm.sudo("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre")
comm.sudo("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tail -n +2 > /tmp/vagrant-network-interfaces.post") comm.sudo("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tac | sed -e '/^#VAGRANT-END/,$ d' | tac > /tmp/vagrant-network-interfaces.post")
# Accumulate the configurations to add to the interfaces file as # Accumulate the configurations to add to the interfaces file as
# well as what interfaces we're actually configuring since we use that # well as what interfaces we're actually configuring since we use that

View File

@ -17,7 +17,7 @@ module VagrantPlugins
virtual = false virtual = false
interface_names = Array.new interface_names = Array.new
machine.communicate.sudo("/usr/sbin/biosdevname; echo $?") do |_, result| machine.communicate.sudo("/usr/sbin/biosdevname; echo $?") do |_, result|
virtual = true if result.chomp == '4' virtual = true if ['4', '127'].include? result.chomp
end end
if virtual if virtual
@ -85,6 +85,7 @@ module VagrantPlugins
interfaces.each do |interface| interfaces.each do |interface|
retryable(on: Vagrant::Errors::VagrantError, tries: 3, sleep: 2) do retryable(on: Vagrant::Errors::VagrantError, tries: 3, sleep: 2) do
machine.communicate.sudo("cat /tmp/vagrant-network-entry_#{interface} >> #{network_scripts_dir}/ifcfg-#{interface}") machine.communicate.sudo("cat /tmp/vagrant-network-entry_#{interface} >> #{network_scripts_dir}/ifcfg-#{interface}")
machine.communicate.sudo("which nmcli >/dev/null 2>&1 && nmcli c reload #{interface}")
machine.communicate.sudo("/sbin/ifdown #{interface}", error_check: true) machine.communicate.sudo("/sbin/ifdown #{interface}", error_check: true)
machine.communicate.sudo("/sbin/ifup #{interface}") machine.communicate.sudo("/sbin/ifup #{interface}")
end end

View File

@ -0,0 +1,23 @@
module VagrantPlugins
module GuestFedora
module Cap
class Flavor
def self.flavor(machine)
# Read the version file
version = nil
machine.communicate.sudo("grep VERSION_ID /etc/os-release") do |type, data|
if type == :stdout
version = data.split("=")[1].chomp.to_i
end
end
if version.nil?
return :fedora
else
return "fedora_#{version}".to_sym
end
end
end
end
end
end

View File

@ -0,0 +1,11 @@
module VagrantPlugins
module GuestFedora
module Cap
class NFSClient
def self.nfs_client_install(machine)
machine.communicate.sudo("yum -y install nfs-utils nfs-utils-lib")
end
end
end
end
end

View File

@ -4,7 +4,7 @@ module VagrantPlugins
module GuestFedora module GuestFedora
class Guest < Vagrant.plugin("2", :guest) class Guest < Vagrant.plugin("2", :guest)
def detect?(machine) def detect?(machine)
machine.communicate.test("grep 'Fedora release [12][678901]' /etc/redhat-release") machine.communicate.test("grep 'Fedora release 1[6789]\\|Fedora release 2[0-9]' /etc/redhat-release")
end end
end end
end end

View File

@ -25,6 +25,16 @@ module VagrantPlugins
require_relative "cap/network_scripts_dir" require_relative "cap/network_scripts_dir"
Cap::NetworkScriptsDir Cap::NetworkScriptsDir
end end
guest_capability("fedora", "flavor") do
require_relative "cap/flavor"
Cap::Flavor
end
guest_capability("fedora", "nfs_client_install") do
require_relative "cap/nfs_client"
Cap::NFSClient
end
end end
end end
end end

View File

@ -11,7 +11,7 @@ module VagrantPlugins
machine.communicate.tap do |comm| machine.communicate.tap do |comm|
if comm.test("test -f ~/.ssh/authorized_keys") if comm.test("test -f ~/.ssh/authorized_keys")
comm.execute( comm.execute(
"sed -i '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys") "sed -i .bak '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys")
end end
end end
end end

View File

@ -27,10 +27,14 @@ module VagrantPlugins
smb_password = Shellwords.shellescape(options[:smb_password]) smb_password = Shellwords.shellescape(options[:smb_password])
# If a domain is provided in the username, separate it
username, domain = (options[:smb_username] || '').split('@', 2)
options[:mount_options] ||= [] options[:mount_options] ||= []
options[:mount_options] << "sec=ntlm" options[:mount_options] << "sec=ntlm"
options[:mount_options] << "username=#{options[:smb_username]}" options[:mount_options] << "username=#{username}"
options[:mount_options] << "pass=#{smb_password}" options[:mount_options] << "pass=#{smb_password}"
options[:mount_options] << "domain=#{domain}" if domain
# First mount command uses getent to get the group # First mount command uses getent to get the group
mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}" mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"

View File

@ -0,0 +1,15 @@
module VagrantPlugins
module GuestPhoton
module Cap
class ChangeHostName
def self.change_host_name(machine, name)
machine.communicate.tap do |comm|
unless comm.test("sudo hostname --fqdn | grep '#{name}'")
comm.sudo("hostname #{name.split('.')[0]}")
end
end
end
end
end
end
end

View File

@ -0,0 +1,42 @@
require 'tempfile'
require 'vagrant/util/template_renderer'
module VagrantPlugins
module GuestPhoton
module Cap
class ConfigureNetworks
include Vagrant::Util
def self.configure_networks(machine, networks)
machine.communicate.tap do |comm|
# Read network interface names
interfaces = []
comm.sudo("ifconfig | grep 'eth' | cut -f1 -d' '") do |_, result|
interfaces = result.split("\n")
end
# Configure interfaces
networks.each do |network|
comm.sudo("ifconfig #{interfaces[network[:interface].to_i]} #{network[:ip]} netmask #{network[:netmask]}")
end
primary_machine_config = machine.env.active_machines.first
primary_machine = machine.env.machine(*primary_machine_config, true)
get_ip = lambda do |machine|
ip = nil
machine.config.vm.networks.each do |type, opts|
if type == :private_network && opts[:ip]
ip = opts[:ip]
break
end
end
ip
end
end
end
end
end
end
end

View File

@ -0,0 +1,11 @@
module VagrantPlugins
module GuestPhoton
module Cap
module Docker
def self.docker_daemon_running(machine)
machine.communicate.test('test -S /run/docker.sock')
end
end
end
end
end

View File

@ -0,0 +1,9 @@
module VagrantPlugins
module GuestPhoton
class Guest < Vagrant.plugin('2', :guest)
def detect?(machine)
machine.communicate.test("cat /etc/photon-release | grep 'VMware Photon Linux'")
end
end
end
end

View File

@ -0,0 +1,30 @@
require 'vagrant'
module VagrantPlugins
module GuestPhoton
class Plugin < Vagrant.plugin('2')
name 'VMware Photon guest'
description 'VMware Photon guest support.'
guest('photon', 'linux') do
require File.expand_path("../guest", __FILE__)
Guest
end
guest_capability('photon', 'change_host_name') do
require_relative 'cap/change_host_name'
Cap::ChangeHostName
end
guest_capability('photon', 'configure_networks') do
require_relative 'cap/configure_networks'
Cap::ConfigureNetworks
end
guest_capability('photon', 'docker_daemon_running') do
require_relative 'cap/docker'
Cap::Docker
end
end
end
end

View File

@ -4,7 +4,6 @@ module VagrantPlugins
class ChangeHostName class ChangeHostName
def self.change_host_name(machine, name) def self.change_host_name(machine, name)
if !machine.communicate.test("hostname | grep '^#{name}$'") if !machine.communicate.test("hostname | grep '^#{name}$'")
machine.communicate.sudo("sh -c 'echo \"#{name}\" > /etc/hostname'")
machine.communicate.sudo("/usr/bin/sethostname #{name}") machine.communicate.sudo("/usr/bin/sethostname #{name}")
end end
end end

View File

@ -16,6 +16,11 @@ module VagrantPlugins
Cap::ConfigureNetworks Cap::ConfigureNetworks
end end
guest_capability("tinycore", "change_host_name") do
require_relative "cap/change_host_name"
Cap::ChangeHostName
end
guest_capability("tinycore", "halt") do guest_capability("tinycore", "halt") do
require_relative "cap/halt" require_relative "cap/halt"
Cap::Halt Cap::Halt

View File

@ -64,7 +64,9 @@ module VagrantPlugins
guest_network.network_adapters.each do |nic| guest_network.network_adapters.each do |nic|
@@logger.debug("nic: #{nic.inspect}") @@logger.debug("nic: #{nic.inspect}")
naked_mac = nic[:mac_address].gsub(':','') naked_mac = nic[:mac_address].gsub(':','')
if driver_mac_address[naked_mac] # If the :net_connection_id entry is nil then it is probably a virtual connection
# and should be ignored.
if driver_mac_address[naked_mac] && !nic[:net_connection_id].nil?
vm_interface_map[driver_mac_address[naked_mac]] = { vm_interface_map[driver_mac_address[naked_mac]] = {
net_connection_id: nic[:net_connection_id], net_connection_id: nic[:net_connection_id],
mac_address: naked_mac, mac_address: naked_mac,

View File

@ -27,6 +27,7 @@ module VagrantPlugins
attr_accessor :box_download_checksum_type attr_accessor :box_download_checksum_type
attr_accessor :box_download_client_cert attr_accessor :box_download_client_cert
attr_accessor :box_download_insecure attr_accessor :box_download_insecure
attr_accessor :box_download_location_trusted
attr_accessor :communicator attr_accessor :communicator
attr_accessor :graceful_halt_timeout attr_accessor :graceful_halt_timeout
attr_accessor :guest attr_accessor :guest
@ -36,6 +37,8 @@ module VagrantPlugins
attr_reader :provisioners attr_reader :provisioners
def initialize def initialize
@logger = Log4r::Logger.new("vagrant::config::vm")
@base_mac = UNSET_VALUE @base_mac = UNSET_VALUE
@boot_timeout = UNSET_VALUE @boot_timeout = UNSET_VALUE
@box = UNSET_VALUE @box = UNSET_VALUE
@ -46,6 +49,7 @@ module VagrantPlugins
@box_download_checksum_type = UNSET_VALUE @box_download_checksum_type = UNSET_VALUE
@box_download_client_cert = UNSET_VALUE @box_download_client_cert = UNSET_VALUE
@box_download_insecure = UNSET_VALUE @box_download_insecure = UNSET_VALUE
@box_download_location_trusted = UNSET_VALUE
@box_url = UNSET_VALUE @box_url = UNSET_VALUE
@box_version = UNSET_VALUE @box_version = UNSET_VALUE
@communicator = UNSET_VALUE @communicator = UNSET_VALUE
@ -357,6 +361,7 @@ module VagrantPlugins
@box_download_checksum_type = nil if @box_download_checksum_type == UNSET_VALUE @box_download_checksum_type = nil if @box_download_checksum_type == UNSET_VALUE
@box_download_client_cert = nil if @box_download_client_cert == UNSET_VALUE @box_download_client_cert = nil if @box_download_client_cert == UNSET_VALUE
@box_download_insecure = false if @box_download_insecure == UNSET_VALUE @box_download_insecure = false if @box_download_insecure == UNSET_VALUE
@box_download_location_trusted = false if @box_download_location_trusted == UNSET_VALUE
@box_url = nil if @box_url == UNSET_VALUE @box_url = nil if @box_url == UNSET_VALUE
@box_version = nil if @box_version == UNSET_VALUE @box_version = nil if @box_version == UNSET_VALUE
@communicator = nil if @communicator == UNSET_VALUE @communicator = nil if @communicator == UNSET_VALUE
@ -443,8 +448,20 @@ module VagrantPlugins
config = config.merge(new_config) config = config.merge(new_config)
end end
rescue Exception => e rescue Exception => e
@logger.error("Vagrantfile load error: #{e.message}")
@logger.error(e.inspect)
@logger.error(e.message)
@logger.error(e.backtrace.join("\n"))
line = "(unknown)"
if e.backtrace && e.backtrace[0]
line = e.backtrace[0].split(":")[1]
end
raise Vagrant::Errors::VagrantfileLoadError, raise Vagrant::Errors::VagrantfileLoadError,
path: "<provider config: #{name}>", path: "<provider config: #{name}>",
line: line,
exception_class: e.class,
message: e.message message: e.message
end end

View File

@ -116,6 +116,7 @@ module VagrantPlugins
end end
b2.use Provision b2.use Provision
b2.use NetSetVLan
b2.use StartInstance b2.use StartInstance
b2.use WaitForIPAddress b2.use WaitForIPAddress
b2.use WaitForCommunicator, [:running] b2.use WaitForCommunicator, [:running]
@ -216,6 +217,7 @@ module VagrantPlugins
autoload :StopInstance, action_root.join('stop_instance') autoload :StopInstance, action_root.join('stop_instance')
autoload :SuspendVM, action_root.join("suspend_vm") autoload :SuspendVM, action_root.join("suspend_vm")
autoload :WaitForIPAddress, action_root.join("wait_for_ip_address") autoload :WaitForIPAddress, action_root.join("wait_for_ip_address")
autoload :NetSetVLan, action_root.join("net_set_vlan")
autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy") autoload :MessageWillNotDestroy, action_root.join("message_will_not_destroy")
end end
end end

View File

@ -55,7 +55,20 @@ module VagrantPlugins
switches = env[:machine].provider.driver.execute("get_switches.ps1", {}) switches = env[:machine].provider.driver.execute("get_switches.ps1", {})
raise Errors::NoSwitches if switches.empty? raise Errors::NoSwitches if switches.empty?
switch = switches[0]["Name"] switch = nil
env[:machine].config.vm.networks.each do |type, opts|
next if type != :public_network && type != :private_network
switchToFind = opts[:bridge]
if switchToFind
puts "Looking for switch with name: #{switchToFind}"
switch = switches.find { |s| s["Name"].downcase == switchToFind.downcase }["Name"]
puts "Found switch: #{switch}"
end
end
if switch.nil?
if switches.length > 1 if switches.length > 1
env[:ui].detail(I18n.t("vagrant_hyperv.choose_switch") + "\n ") env[:ui].detail(I18n.t("vagrant_hyperv.choose_switch") + "\n ")
switches.each_index do |i| switches.each_index do |i|
@ -72,6 +85,9 @@ module VagrantPlugins
switch = nil if switch < 0 || switch >= switches.length switch = nil if switch < 0 || switch >= switches.length
end end
switch = switches[switch]["Name"] switch = switches[switch]["Name"]
else
switch = switches[0]["Name"]
end
end end
env[:ui].detail("Cloning virtual hard drive...") env[:ui].detail("Cloning virtual hard drive...")

View File

@ -0,0 +1,20 @@
module VagrantPlugins
module HyperV
module Action
class NetSetVLan
def initialize(app, env)
@app = app
end
def call(env)
vlan_id = env[:machine].provider_config.vlan_id
if vlan_id
env[:ui].info("[Settings] [Network Adapter] Setting Vlan ID to: #{vlan_id}")
env[:machine].provider.driver.net_set_vlan(vlan_id)
end
@app.call(env)
end
end
end
end
end

View File

@ -3,15 +3,13 @@ require "vagrant"
module VagrantPlugins module VagrantPlugins
module HyperV module HyperV
class Config < Vagrant.plugin("2", :config) class Config < Vagrant.plugin("2", :config)
# The timeout to wait for an IP address when booting the machine,
# in seconds. attr_accessor :ip_address_timeout # Time to wait for an IP address when booting, in seconds @return [Integer]
# attr_accessor :memory # Memory size in mb @return [Integer]
# @return [Integer] attr_accessor :maxmemory # Maximal memory size in mb enables dynamical memory allocation @return [Integer]
attr_accessor :ip_address_timeout attr_accessor :cpus # Number of cpu's @return [Integer]
attr_accessor :memory attr_accessor :vmname # Name that will be shoen in Hyperv Manager @return [String]
attr_accessor :maxmemory attr_accessor :vlan_id # VLAN ID for network interface for the virtual machine. @return [Integer]
attr_accessor :cpus
attr_accessor :vmname
def initialize def initialize
@ip_address_timeout = UNSET_VALUE @ip_address_timeout = UNSET_VALUE
@ -19,6 +17,7 @@ module VagrantPlugins
@maxmemory = UNSET_VALUE @maxmemory = UNSET_VALUE
@cpus = UNSET_VALUE @cpus = UNSET_VALUE
@vmname = UNSET_VALUE @vmname = UNSET_VALUE
@vlan_id = UNSET_VALUE
end end
def finalize! def finalize!
@ -29,6 +28,7 @@ module VagrantPlugins
@maxmemory = nil if @maxmemory == UNSET_VALUE @maxmemory = nil if @maxmemory == UNSET_VALUE
@cpus = nil if @cpus == UNSET_VALUE @cpus = nil if @cpus == UNSET_VALUE
@vmname = nil if @vmname == UNSET_VALUE @vmname = nil if @vmname == UNSET_VALUE
@vlan_id = nil if @vlan_id == UNSET_VALUE
end end
def validate(machine) def validate(machine)

View File

@ -77,6 +77,10 @@ module VagrantPlugins
execute('import_vm.ps1', options) execute('import_vm.ps1', options)
end end
def net_set_vlan(vlan_id)
execute("set_network_vlan.ps1", { VmId: vm_id, VlanId: vlan_id })
end
protected protected
def execute_powershell(path, options, &block) def execute_powershell(path, options, &block)

View File

@ -136,12 +136,15 @@ $vm | Set-VM @more_vm_params -Passthru
# Add drives to the virtual machine # Add drives to the virtual machine
$controllers = Select-Xml -xml $vmconfig -xpath "//*[starts-with(name(.),'controller')]" $controllers = Select-Xml -xml $vmconfig -xpath "//*[starts-with(name(.),'controller')]"
# Only set EFI secure boot for Gen 2 machines, not gen 1
if ($generation -ne 1) {
# Set EFI secure boot # Set EFI secure boot
if ($secure_boot_enabled -eq "True") { if ($secure_boot_enabled -eq "True") {
Set-VMFirmware -VM $vm -EnableSecureBoot On Set-VMFirmware -VM $vm -EnableSecureBoot On
} else { } else {
Set-VMFirmware -VM $vm -EnableSecureBoot Off Set-VMFirmware -VM $vm -EnableSecureBoot Off
} }
}
# A regular expression pattern to pull the number from controllers # A regular expression pattern to pull the number from controllers
[regex]$rx="\d" [regex]$rx="\d"

View File

@ -0,0 +1,18 @@
param (
[string]$VmId = $(throw "-VmId is required."),
[int]$VlanId = $(throw "-VlanId ")
)
# Include the following modules
$presentDir = Split-Path -parent $PSCommandPath
$modules = @()
$modules += $presentDir + "\utils\write_messages.ps1"
forEach ($module in $modules) { . $module }
try {
$vm = Get-VM -Id $VmId -ErrorAction "stop"
Set-VMNetworkAdapterVlan $vm -Access -Vlanid $VlanId
}
catch {
Write-Error-Message "Failed to set VM's Vlan ID $_"
}

View File

@ -157,7 +157,7 @@ module VagrantPlugins
@logger.debug("Bridge was directly specified in config, searching for: #{config[:bridge]}") @logger.debug("Bridge was directly specified in config, searching for: #{config[:bridge]}")
# Search for a matching bridged interface # Search for a matching bridged interface
bridge = config[:bridge] Array(config[:bridge]).each do |bridge|
bridge = bridge.downcase if bridge.respond_to?(:downcase) bridge = bridge.downcase if bridge.respond_to?(:downcase)
bridgedifs.each do |interface| bridgedifs.each do |interface|
if bridge === interface[:name].downcase if bridge === interface[:name].downcase
@ -166,6 +166,8 @@ module VagrantPlugins
break break
end end
end end
break if chosen_bridge
end
# If one wasn't found, then we notify the user here. # If one wasn't found, then we notify the user here.
if !chosen_bridge if !chosen_bridge

View File

@ -49,7 +49,8 @@ module VagrantPlugins
"4.0" => Version_4_0, "4.0" => Version_4_0,
"4.1" => Version_4_1, "4.1" => Version_4_1,
"4.2" => Version_4_2, "4.2" => Version_4_2,
"4.3" => Version_4_3 "4.3" => Version_4_3,
"5.0" => Version_5_0,
} }
if @version.start_with?("4.2.14") if @version.start_with?("4.2.14")

View File

@ -496,10 +496,14 @@ module VagrantPlugins
def share_folders(folders) def share_folders(folders)
folders.each do |folder| folders.each do |folder|
hostpath = folder[:hostpath]
if Vagrant::Util::Platform.windows?
hostpath = Vagrant::Util::Platform.windows_unc_path(hostpath)
end
args = ["--name", args = ["--name",
folder[:name], folder[:name],
"--hostpath", "--hostpath",
folder[:hostpath]] hostpath]
args << "--transient" if folder.key?(:transient) && folder[:transient] args << "--transient" if folder.key?(:transient) && folder[:transient]
# Enable symlinks on the shared folder # Enable symlinks on the shared folder

View File

@ -0,0 +1,619 @@
require 'log4r'
require "vagrant/util/platform"
require File.expand_path("../base", __FILE__)
module VagrantPlugins
module ProviderVirtualBox
module Driver
# Driver for VirtualBox 5.0.x
class Version_5_0 < Base
def initialize(uuid)
super()
@logger = Log4r::Logger.new("vagrant::provider::virtualbox_5_0")
@uuid = uuid
end
def clear_forwarded_ports
args = []
read_forwarded_ports(@uuid).each do |nic, name, _, _|
args.concat(["--natpf#{nic}", "delete", name])
end
execute("modifyvm", @uuid, *args) if !args.empty?
end
def clear_shared_folders
info = execute("showvminfo", @uuid, "--machinereadable", retryable: true)
info.split("\n").each do |line|
if line =~ /^SharedFolderNameMachineMapping\d+="(.+?)"$/
execute("sharedfolder", "remove", @uuid, "--name", $1.to_s)
end
end
end
def create_dhcp_server(network, options)
execute("dhcpserver", "add", "--ifname", network,
"--ip", options[:dhcp_ip],
"--netmask", options[:netmask],
"--lowerip", options[:dhcp_lower],
"--upperip", options[:dhcp_upper],
"--enable")
end
def create_host_only_network(options)
# Create the interface
execute("hostonlyif", "create") =~ /^Interface '(.+?)' was successfully created$/
name = $1.to_s
# Configure it
execute("hostonlyif", "ipconfig", name,
"--ip", options[:adapter_ip],
"--netmask", options[:netmask])
# Return the details
return {
name: name,
ip: options[:adapter_ip],
netmask: options[:netmask],
dhcp: nil
}
end
def delete
execute("unregistervm", @uuid, "--delete")
end
def delete_unused_host_only_networks
networks = []
execute("list", "hostonlyifs", retryable: true).split("\n").each do |line|
networks << $1.to_s if line =~ /^Name:\s+(.+?)$/
end
execute("list", "vms", retryable: true).split("\n").each do |line|
if line =~ /^".+?"\s+\{(.+?)\}$/
info = execute("showvminfo", $1.to_s, "--machinereadable", retryable: true)
info.split("\n").each do |inner_line|
if inner_line =~ /^hostonlyadapter\d+="(.+?)"$/
networks.delete($1.to_s)
end
end
end
end
networks.each do |name|
# First try to remove any DHCP servers attached. We use `raw` because
# it is okay if this fails. It usually means that a DHCP server was
# never attached.
raw("dhcpserver", "remove", "--ifname", name)
# Delete the actual host only network interface.
execute("hostonlyif", "remove", name)
end
end
def discard_saved_state
execute("discardstate", @uuid)
end
def enable_adapters(adapters)
args = []
adapters.each do |adapter|
args.concat(["--nic#{adapter[:adapter]}", adapter[:type].to_s])
if adapter[:bridge]
args.concat(["--bridgeadapter#{adapter[:adapter]}",
adapter[:bridge], "--cableconnected#{adapter[:adapter]}", "on"])
end
if adapter[:hostonly]
args.concat(["--hostonlyadapter#{adapter[:adapter]}",
adapter[:hostonly], "--cableconnected#{adapter[:adapter]}", "on"])
end
if adapter[:intnet]
args.concat(["--intnet#{adapter[:adapter]}",
adapter[:intnet], "--cableconnected#{adapter[:adapter]}", "on"])
end
if adapter[:mac_address]
args.concat(["--macaddress#{adapter[:adapter]}",
adapter[:mac_address]])
end
if adapter[:nic_type]
args.concat(["--nictype#{adapter[:adapter]}", adapter[:nic_type].to_s])
end
end
execute("modifyvm", @uuid, *args)
end
def execute_command(command)
execute(*command)
end
def export(path)
execute("export", @uuid, "--output", path.to_s)
end
def forward_ports(ports)
args = []
ports.each do |options|
pf_builder = [options[:name],
options[:protocol] || "tcp",
options[:hostip] || "",
options[:hostport],
options[:guestip] || "",
options[:guestport]]
args.concat(["--natpf#{options[:adapter] || 1}",
pf_builder.join(",")])
end
execute("modifyvm", @uuid, *args) if !args.empty?
end
def halt
execute("controlvm", @uuid, "poweroff")
end
def import(ovf)
ovf = Vagrant::Util::Platform.cygwin_windows_path(ovf)
output = ""
total = ""
last = 0
# Dry-run the import to get the suggested name and path
@logger.debug("Doing dry-run import to determine parallel-safe name...")
output = execute("import", "-n", ovf)
result = /Suggested VM name "(.+?)"/.match(output)
if !result
raise Vagrant::Errors::VirtualBoxNoName, output: output
end
suggested_name = result[1].to_s
# Append millisecond plus a random to the path in case we're
# importing the same box elsewhere.
specified_name = "#{suggested_name}_#{(Time.now.to_f * 1000.0).to_i}_#{rand(100000)}"
@logger.debug("-- Parallel safe name: #{specified_name}")
# Build the specified name param list
name_params = [
"--vsys", "0",
"--vmname", specified_name,
]
# Extract the disks list and build the disk target params
disk_params = []
disks = output.scan(/(\d+): Hard disk image: source image=.+, target path=(.+),/)
disks.each do |unit_num, path|
disk_params << "--vsys"
disk_params << "0"
disk_params << "--unit"
disk_params << unit_num
disk_params << "--disk"
if Vagrant::Util::Platform.windows?
# we use the block form of sub here to ensure that if the specified_name happens to end with a number (which is fairly likely) then
# we won't end up having the character sequence of a \ followed by a number be interpreted as a back reference. For example, if
# specified_name were "abc123", then "\\abc123\\".reverse would be "\\321cba\\", and the \3 would be treated as a back reference by the sub
disk_params << path.reverse.sub("\\#{suggested_name}\\".reverse) { "\\#{specified_name}\\".reverse }.reverse # Replace only last occurrence
else
disk_params << path.reverse.sub("/#{suggested_name}/".reverse, "/#{specified_name}/".reverse).reverse # Replace only last occurrence
end
end
execute("import", ovf , *name_params, *disk_params) do |type, data|
if type == :stdout
# Keep track of the stdout so that we can get the VM name
output << data
elsif type == :stderr
# Append the data so we can see the full view
total << data.gsub("\r", "")
# Break up the lines. We can't get the progress until we see an "OK"
lines = total.split("\n")
if lines.include?("OK.")
# The progress of the import will be in the last line. Do a greedy
# regular expression to find what we're looking for.
match = /.+(\d{2})%/.match(lines.last)
if match
current = match[1].to_i
if current > last
last = current
yield current if block_given?
end
end
end
end
end
output = execute("list", "vms", retryable: true)
match = /^"#{Regexp.escape(specified_name)}" \{(.+?)\}$/.match(output)
return match[1].to_s if match
nil
end
def max_network_adapters
36
end
def read_forwarded_ports(uuid=nil, active_only=false)
uuid ||= @uuid
@logger.debug("read_forward_ports: uuid=#{uuid} active_only=#{active_only}")
results = []
current_nic = nil
info = execute("showvminfo", uuid, "--machinereadable", retryable: true)
info.split("\n").each do |line|
# This is how we find the nic that a FP is attached to,
# since this comes first.
current_nic = $1.to_i if line =~ /^nic(\d+)=".+?"$/
# If we care about active VMs only, then we check the state
# to verify the VM is running.
if active_only && line =~ /^VMState="(.+?)"$/ && $1.to_s != "running"
return []
end
# Parse out the forwarded port information
if line =~ /^Forwarding.+?="(.+?),.+?,.*?,(.+?),.*?,(.+?)"$/
result = [current_nic, $1.to_s, $2.to_i, $3.to_i]
@logger.debug(" - #{result.inspect}")
results << result
end
end
results
end
def read_bridged_interfaces
execute("list", "bridgedifs").split("\n\n").collect do |block|
info = {}
block.split("\n").each do |line|
if line =~ /^Name:\s+(.+?)$/
info[:name] = $1.to_s
elsif line =~ /^IPAddress:\s+(.+?)$/
info[:ip] = $1.to_s
elsif line =~ /^NetworkMask:\s+(.+?)$/
info[:netmask] = $1.to_s
elsif line =~ /^Status:\s+(.+?)$/
info[:status] = $1.to_s
end
end
# Return the info to build up the results
info
end
end
def read_dhcp_servers
execute("list", "dhcpservers", retryable: true).split("\n\n").collect do |block|
info = {}
block.split("\n").each do |line|
if network = line[/^NetworkName:\s+HostInterfaceNetworking-(.+?)$/, 1]
info[:network] = network
info[:network_name] = "HostInterfaceNetworking-#{network}"
elsif ip = line[/^IP:\s+(.+?)$/, 1]
info[:ip] = ip
elsif netmask = line[/^NetworkMask:\s+(.+?)$/, 1]
info[:netmask] = netmask
elsif lower = line[/^lowerIPAddress:\s+(.+?)$/, 1]
info[:lower] = lower
elsif upper = line[/^upperIPAddress:\s+(.+?)$/, 1]
info[:upper] = upper
end
end
info
end
end
def read_guest_additions_version
output = execute("guestproperty", "get", @uuid, "/VirtualBox/GuestAdd/Version",
retryable: true)
if output =~ /^Value: (.+?)$/
# Split the version by _ since some distro versions modify it
# to look like this: 4.1.2_ubuntu, and the distro part isn't
# too important.
value = $1.to_s
return value.split("_").first
end
# If we can't get the guest additions version by guest property, try
# to get it from the VM info itself.
info = execute("showvminfo", @uuid, "--machinereadable", retryable: true)
info.split("\n").each do |line|
return $1.to_s if line =~ /^GuestAdditionsVersion="(.+?)"$/
end
return nil
end
def read_guest_ip(adapter_number)
ip = read_guest_property("/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP")
if !valid_ip_address?(ip)
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound,
guest_property: "/VirtualBox/GuestInfo/Net/#{adapter_number}/V4/IP"
end
return ip
end
def read_guest_property(property)
output = execute("guestproperty", "get", @uuid, property)
if output =~ /^Value: (.+?)$/
$1.to_s
else
raise Vagrant::Errors::VirtualBoxGuestPropertyNotFound, guest_property: property
end
end
def read_host_only_interfaces
execute("list", "hostonlyifs", retryable: true).split("\n\n").collect do |block|
info = {}
block.split("\n").each do |line|
if line =~ /^Name:\s+(.+?)$/
info[:name] = $1.to_s
elsif line =~ /^IPAddress:\s+(.+?)$/
info[:ip] = $1.to_s
elsif line =~ /^NetworkMask:\s+(.+?)$/
info[:netmask] = $1.to_s
elsif line =~ /^Status:\s+(.+?)$/
info[:status] = $1.to_s
end
end
info
end
end
def read_mac_address
info = execute("showvminfo", @uuid, "--machinereadable", retryable: true)
info.split("\n").each do |line|
return $1.to_s if line =~ /^macaddress1="(.+?)"$/
end
nil
end
def read_mac_addresses
macs = {}
info = execute("showvminfo", @uuid, "--machinereadable", retryable: true)
info.split("\n").each do |line|
if matcher = /^macaddress(\d+)="(.+?)"$/.match(line)
adapter = matcher[1].to_i
mac = matcher[2].to_s
macs[adapter] = mac
end
end
macs
end
def read_machine_folder
execute("list", "systemproperties", retryable: true).split("\n").each do |line|
if line =~ /^Default machine folder:\s+(.+?)$/i
return $1.to_s
end
end
nil
end
def read_network_interfaces
nics = {}
info = execute("showvminfo", @uuid, "--machinereadable", retryable: true)
info.split("\n").each do |line|
if line =~ /^nic(\d+)="(.+?)"$/
adapter = $1.to_i
type = $2.to_sym
nics[adapter] ||= {}
nics[adapter][:type] = type
elsif line =~ /^hostonlyadapter(\d+)="(.+?)"$/
adapter = $1.to_i
network = $2.to_s
nics[adapter] ||= {}
nics[adapter][:hostonly] = network
elsif line =~ /^bridgeadapter(\d+)="(.+?)"$/
adapter = $1.to_i
network = $2.to_s
nics[adapter] ||= {}
nics[adapter][:bridge] = network
end
end
nics
end
def read_state
output = execute("showvminfo", @uuid, "--machinereadable", retryable: true)
if output =~ /^name="<inaccessible>"$/
return :inaccessible
elsif output =~ /^VMState="(.+?)"$/
return $1.to_sym
end
nil
end
def read_used_ports
ports = []
execute("list", "vms", retryable: true).split("\n").each do |line|
if line =~ /^".+?" \{(.+?)\}$/
uuid = $1.to_s
# Ignore our own used ports
next if uuid == @uuid
read_forwarded_ports(uuid, true).each do |_, _, hostport, _|
ports << hostport
end
end
end
ports
end
def read_vms
results = {}
execute("list", "vms", retryable: true).split("\n").each do |line|
if line =~ /^"(.+?)" \{(.+?)\}$/
results[$1.to_s] = $2.to_s
end
end
results
end
def remove_dhcp_server(network_name)
execute("dhcpserver", "remove", "--netname", network_name)
end
def set_mac_address(mac)
execute("modifyvm", @uuid, "--macaddress1", mac)
end
def set_name(name)
execute("modifyvm", @uuid, "--name", name, retryable: true)
rescue Vagrant::Errors::VBoxManageError => e
raise if !e.extra_data[:stderr].include?("VERR_ALREADY_EXISTS")
# We got VERR_ALREADY_EXISTS. This means that we're renaming to
# a VM name that already exists. Raise a custom error.
raise Vagrant::Errors::VirtualBoxNameExists,
stderr: e.extra_data[:stderr]
end
def share_folders(folders)
folders.each do |folder|
hostpath = folder[:hostpath]
if Vagrant::Util::Platform.windows?
hostpath = Vagrant::Util::Platform.windows_unc_path(hostpath)
end
args = ["--name",
folder[:name],
"--hostpath",
hostpath]
args << "--transient" if folder.key?(:transient) && folder[:transient]
# Enable symlinks on the shared folder
execute("setextradata", @uuid, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{folder[:name]}", "1")
# Add the shared folder
execute("sharedfolder", "add", @uuid, *args)
end
end
def ssh_port(expected_port)
@logger.debug("Searching for SSH port: #{expected_port.inspect}")
# Look for the forwarded port only by comparing the guest port
read_forwarded_ports.each do |_, _, hostport, guestport|
return hostport if guestport == expected_port
end
nil
end
def resume
@logger.debug("Resuming paused VM...")
execute("controlvm", @uuid, "resume")
end
def start(mode)
command = ["startvm", @uuid, "--type", mode.to_s]
r = raw(*command)
if r.exit_code == 0 || r.stdout =~ /VM ".+?" has been successfully started/
# Some systems return an exit code 1 for some reason. For that
# we depend on the output.
return true
end
# If we reached this point then it didn't work out.
raise Vagrant::Errors::VBoxManageError,
command: command.inspect,
stderr: r.stderr
end
def suspend
execute("controlvm", @uuid, "savestate")
end
def unshare_folders(names)
names.each do |name|
begin
execute(
"sharedfolder", "remove", @uuid,
"--name", name,
"--transient")
execute(
"setextradata", @uuid,
"VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{name}")
rescue Vagrant::Errors::VBoxManageError => e
if e.extra_data[:stderr].include?("VBOX_E_FILE_ERROR")
# The folder doesn't exist. ignore.
else
raise
end
end
end
end
def verify!
# This command sometimes fails if kernel drivers aren't properly loaded
# so we just run the command and verify that it succeeded.
execute("list", "hostonlyifs", retryable: true)
end
def verify_image(path)
r = raw("import", path.to_s, "--dry-run")
return r.exit_code == 0
end
def vm_exists?(uuid)
5.times do |i|
result = raw("showvminfo", uuid)
return true if result.exit_code == 0
# GH-2479: Sometimes this happens. In this case, retry. If
# we don't see this text, the VM really probably doesn't exist.
return false if !result.stderr.include?("CO_E_SERVER_EXEC_FAILURE")
# Sleep a bit though to give VirtualBox time to fix itself
sleep 2
end
# If we reach this point, it means that we consistently got the
# failure, do a standard vboxmanage now. This will raise an
# exception if it fails again.
execute("showvminfo", uuid)
return true
end
protected
def valid_ip_address?(ip)
# Filter out invalid IP addresses
# GH-4658 VirtualBox can report an IP address of 0.0.0.0 for FreeBSD guests.
if ip == "0.0.0.0"
return false
else
return true
end
end
end
end
end
end

View File

@ -45,6 +45,7 @@ module VagrantPlugins
autoload :Version_4_1, File.expand_path("../driver/version_4_1", __FILE__) autoload :Version_4_1, File.expand_path("../driver/version_4_1", __FILE__)
autoload :Version_4_2, File.expand_path("../driver/version_4_2", __FILE__) autoload :Version_4_2, File.expand_path("../driver/version_4_2", __FILE__)
autoload :Version_4_3, File.expand_path("../driver/version_4_3", __FILE__) autoload :Version_4_3, File.expand_path("../driver/version_4_3", __FILE__)
autoload :Version_5_0, File.expand_path("../driver/version_5_0", __FILE__)
end end
module Model module Model

View File

@ -68,9 +68,16 @@ module VagrantPlugins
# Some Ansible options must be passed as environment variables, # Some Ansible options must be passed as environment variables,
# as there is no equivalent command line arguments # as there is no equivalent command line arguments
"ANSIBLE_FORCE_COLOR" => "true",
"ANSIBLE_HOST_KEY_CHECKING" => "#{config.host_key_checking}", "ANSIBLE_HOST_KEY_CHECKING" => "#{config.host_key_checking}",
} }
# When Ansible output is piped in Vagrant integration, its default colorization is
# automatically disabled and the only way to re-enable colors is to use ANSIBLE_FORCE_COLOR.
env["ANSIBLE_FORCE_COLOR"] = "true" if @machine.env.ui.is_a?(Vagrant::UI::Colored)
# Setting ANSIBLE_NOCOLOR is "unnecessary" at the moment, but this could change in the future
# (e.g. local provisioner [GH-2103], possible change in vagrant/ansible integration, etc.)
env["ANSIBLE_NOCOLOR"] = "true" unless @machine.env.ui.is_a?(Vagrant::UI::Colored)
# ANSIBLE_SSH_ARGS is required for Multiple SSH keys, SSH forwarding and custom SSH settings # ANSIBLE_SSH_ARGS is required for Multiple SSH keys, SSH forwarding and custom SSH settings
env["ANSIBLE_SSH_ARGS"] = ansible_ssh_args unless ansible_ssh_args.empty? env["ANSIBLE_SSH_ARGS"] = ansible_ssh_args unless ansible_ssh_args.empty?

View File

@ -0,0 +1,20 @@
module VagrantPlugins
module Chef
module Cap
module Windows
module ChefInstalled
# Check if Chef is installed at the given version.
# @return [true, false]
def self.chef_installed(machine, version)
if version != :latest
command = 'if ((&knife --version) -Match "Chef: "' + version + '"){ exit 0 } else { exit 1 }'
else
command = 'if ((&knife --version) -Match "Chef: *"){ exit 0 } else { exit 1 }'
end
machine.communicate.test(command, sudo: true)
end
end
end
end
end
end

View File

@ -58,6 +58,11 @@ module VagrantPlugins
Cap::Linux::ChefInstalled Cap::Linux::ChefInstalled
end end
guest_capability(:windows, :chef_installed) do
require_relative "cap/windows/chef_installed"
Cap::Windows::ChefInstalled
end
guest_capability(:debian, :chef_install) do guest_capability(:debian, :chef_install) do
require_relative "cap/debian/chef_install" require_relative "cap/debian/chef_install"
Cap::Debian::ChefInstall Cap::Debian::ChefInstall

View File

@ -37,8 +37,14 @@ module VagrantPlugins
def verify_binary(binary) def verify_binary(binary)
# Checks for the existence of chef binary and error if it # Checks for the existence of chef binary and error if it
# doesn't exist. # doesn't exist.
if windows?
command = "if ((&'#{binary}' -v) -Match 'Chef: *'){ exit 0 } else { exit 1 }"
else
command = "sh -c 'command -v #{binary}'"
end
@machine.communicate.sudo( @machine.communicate.sudo(
"sh -c 'command -v #{binary}'", command,
error_class: ChefError, error_class: ChefError,
error_key: :chef_not_detected, error_key: :chef_not_detected,
binary: binary, binary: binary,
@ -66,11 +72,15 @@ module VagrantPlugins
@machine.communicate.tap do |comm| @machine.communicate.tap do |comm|
paths.each do |path| paths.each do |path|
if windows?
comm.sudo("mkdir ""#{path}"" -f")
else
comm.sudo("mkdir -p #{path}") comm.sudo("mkdir -p #{path}")
comm.sudo("chown -h #{@machine.ssh_info[:username]} #{path}") comm.sudo("chown -h #{@machine.ssh_info[:username]} #{path}")
end end
end end
end end
end
def setup_config(template, filename, template_vars) def setup_config(template, filename, template_vars)
# If we have custom configuration, upload it # If we have custom configuration, upload it
@ -133,7 +143,13 @@ module VagrantPlugins
remote_file = File.join(@config.provisioning_path, "dna.json") remote_file = File.join(@config.provisioning_path, "dna.json")
@machine.communicate.tap do |comm| @machine.communicate.tap do |comm|
comm.sudo("rm -f #{remote_file}", error_check: false) if windows?
command = "if (test-path '#{remote_file}') {rm '#{remote_file}' -force -recurse}"
else
command = "rm -f #{remote_file}"
end
comm.sudo(command, error_check: false)
comm.upload(temp.path, remote_file) comm.upload(temp.path, remote_file)
end end
end end
@ -146,7 +162,13 @@ module VagrantPlugins
"vagrant.provisioners.chef.upload_encrypted_data_bag_secret_key") "vagrant.provisioners.chef.upload_encrypted_data_bag_secret_key")
@machine.communicate.tap do |comm| @machine.communicate.tap do |comm|
comm.sudo("rm -f #{remote_file}", error_check: false) if windows?
command = "if (test-path ""#{remote_file}"") {rm ""#{remote_file}"" -force -recurse}"
else
command = "rm -f #{remote_file}"
end
comm.sudo(command, error_check: false)
comm.upload(encrypted_data_bag_secret_key_path, remote_file) comm.upload(encrypted_data_bag_secret_key_path, remote_file)
end end
end end
@ -154,7 +176,13 @@ module VagrantPlugins
def delete_encrypted_data_bag_secret def delete_encrypted_data_bag_secret
remote_file = guest_encrypted_data_bag_secret_key_path remote_file = guest_encrypted_data_bag_secret_key_path
if remote_file if remote_file
@machine.communicate.sudo("rm -f #{remote_file}", error_check: false) if windows?
command = "if (test-path ""#{remote_file}"") {rm ""#{remote_file}"" -force -recurse}"
else
command = "rm -f #{remote_file}"
end
@machine.communicate.sudo(command, error_check: false)
end end
end end

View File

@ -18,8 +18,12 @@ module VagrantPlugins
user = @machine.ssh_info[:username] user = @machine.ssh_info[:username]
# Reset upload path permissions for the current ssh user # Reset upload path permissions for the current ssh user
if windows?
@machine.communicate.sudo("mkdir ""#{config.upload_path}"" -f")
else
@machine.communicate.sudo("mkdir -p #{config.upload_path}") @machine.communicate.sudo("mkdir -p #{config.upload_path}")
@machine.communicate.sudo("chown -R #{user} #{config.upload_path}") @machine.communicate.sudo("chown -R #{user} #{config.upload_path}")
end
# Upload the recipe # Upload the recipe
upload_recipe upload_recipe

View File

@ -39,8 +39,12 @@ module VagrantPlugins
@machine.ui.info I18n.t("vagrant.provisioners.chef.client_key_folder") @machine.ui.info I18n.t("vagrant.provisioners.chef.client_key_folder")
path = Pathname.new(@config.client_key_path) path = Pathname.new(@config.client_key_path)
if windows?
@machine.communicate.sudo("mkdir ""#{path.dirname}"" -f")
else
@machine.communicate.sudo("mkdir -p #{path.dirname}") @machine.communicate.sudo("mkdir -p #{path.dirname}")
end end
end
def upload_validation_key def upload_validation_key
@machine.ui.info I18n.t("vagrant.provisioners.chef.upload_validation_key") @machine.ui.info I18n.t("vagrant.provisioners.chef.upload_validation_key")

View File

@ -7,8 +7,7 @@ module VagrantPlugins
machine.communicate.tap do |comm| machine.communicate.tap do |comm|
if !comm.test('grep -q \'\-r=true\' /etc/default/docker') if !comm.test('grep -q \'\-r=true\' /etc/default/docker')
comm.sudo("echo 'DOCKER_OPTS=\"-r=true ${DOCKER_OPTS}\"' >> /etc/default/docker") comm.sudo("echo 'DOCKER_OPTS=\"-r=true ${DOCKER_OPTS}\"' >> /etc/default/docker")
comm.sudo("stop docker") comm.sudo("service docker restart")
comm.sudo("start docker")
# Wait some amount time for the pid to become available # Wait some amount time for the pid to become available
# so that we don't start executing Docker commands until # so that we don't start executing Docker commands until

View File

@ -15,7 +15,7 @@ module VagrantPlugins
comm.sudo("apt-get update -y") comm.sudo("apt-get update -y")
comm.sudo("apt-get install -y --force-yes -q curl") comm.sudo("apt-get install -y --force-yes -q curl")
comm.sudo("curl -sSL https://get.docker.com/gpg | apt-key add -") comm.sudo("curl -sSL https://get.docker.com/gpg | apt-key add -")
comm.sudo("echo deb http://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list") comm.sudo("echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list")
comm.sudo("apt-get update") comm.sudo("apt-get update")
comm.sudo("echo lxc lxc/directory string /var/lib/lxc | debconf-set-selections") comm.sudo("echo lxc lxc/directory string /var/lib/lxc | debconf-set-selections")
comm.sudo("apt-get install -y --force-yes -q xz-utils #{package} -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'") comm.sudo("apt-get install -y --force-yes -q xz-utils #{package} -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'")

View File

@ -2,22 +2,33 @@ module VagrantPlugins
module Puppet module Puppet
module Config module Config
class Puppet < Vagrant.plugin("2", :config) class Puppet < Vagrant.plugin("2", :config)
# The path to Puppet's bin/ directory.
# @return [String]
attr_accessor :binary_path
attr_accessor :facter attr_accessor :facter
attr_accessor :hiera_config_path attr_accessor :hiera_config_path
attr_accessor :manifest_file attr_accessor :manifest_file
attr_accessor :manifests_path attr_accessor :manifests_path
attr_accessor :environment
attr_accessor :environment_path
attr_accessor :module_path attr_accessor :module_path
attr_accessor :options attr_accessor :options
attr_accessor :synced_folder_type attr_accessor :synced_folder_type
attr_accessor :synced_folder_args
attr_accessor :temp_dir attr_accessor :temp_dir
attr_accessor :working_directory attr_accessor :working_directory
def initialize def initialize
super super
@binary_path = UNSET_VALUE
@hiera_config_path = UNSET_VALUE @hiera_config_path = UNSET_VALUE
@manifest_file = UNSET_VALUE @manifest_file = UNSET_VALUE
@manifests_path = UNSET_VALUE @manifests_path = UNSET_VALUE
@environment = UNSET_VALUE
@environment_path = UNSET_VALUE
@module_path = UNSET_VALUE @module_path = UNSET_VALUE
@options = [] @options = []
@facter = {} @facter = {}
@ -41,26 +52,47 @@ module VagrantPlugins
def merge(other) def merge(other)
super.tap do |result| super.tap do |result|
result.facter = @facter.merge(other.facter) result.facter = @facter.merge(other.facter)
result.environment_path = @facter.merge(other.environment_path)
result.environment = @facter.merge(other.environment)
end end
end end
def finalize! def finalize!
super super
if @manifests_path == UNSET_VALUE if @environment_path == UNSET_VALUE && @manifests_path == UNSET_VALUE
#If both are unset, assume 'manifests' mode for now. TBD: Switch to environments by default?
@manifests_path = [:host, "manifests"] @manifests_path = [:host, "manifests"]
end end
if @manifests_path && !@manifests_path.is_a?(Array) # If the paths are just strings, assume they are 'host' paths (rather than guest)
if @environment_path != UNSET_VALUE && !@environment_path.is_a?(Array)
@environment_path = [:host, @environment_path]
end
if @manifests_path != UNSET_VALUE && !@manifests_path.is_a?(Array)
@manifests_path = [:host, @manifests_path] @manifests_path = [:host, @manifests_path]
end end
@manifests_path[0] = @manifests_path[0].to_sym
@hiera_config_path = nil if @hiera_config_path == UNSET_VALUE @hiera_config_path = nil if @hiera_config_path == UNSET_VALUE
if @environment_path == UNSET_VALUE
@manifests_path[0] = @manifests_path[0].to_sym
@environment_path = nil
@manifest_file = "default.pp" if @manifest_file == UNSET_VALUE @manifest_file = "default.pp" if @manifest_file == UNSET_VALUE
else
@environment_path[0] = @environment_path[0].to_sym
@environment = "production" if @environment == UNSET_VALUE
if @manifests_path == UNSET_VALUE
@manifests_path = nil
end
if @manifest_file == UNSET_VALUE
@manifest_file = nil
end
end
@binary_path = nil if @binary_path == UNSET_VALUE
@module_path = nil if @module_path == UNSET_VALUE @module_path = nil if @module_path == UNSET_VALUE
@synced_folder_type = nil if @synced_folder_type == UNSET_VALUE @synced_folder_type = nil if @synced_folder_type == UNSET_VALUE
@synced_folder_args = nil if @synced_folder_args == UNSET_VALUE
@temp_dir = "/tmp/vagrant-puppet" if @temp_dir == UNSET_VALUE @temp_dir = "/tmp/vagrant-puppet" if @temp_dir == UNSET_VALUE
@working_directory = nil if @working_directory == UNSET_VALUE @working_directory = nil if @working_directory == UNSET_VALUE
end end
@ -86,7 +118,7 @@ module VagrantPlugins
this_expanded_module_paths = expanded_module_paths(machine.env.root_path) this_expanded_module_paths = expanded_module_paths(machine.env.root_path)
# Manifests path/file validation # Manifests path/file validation
if manifests_path[0].to_sym == :host if manifests_path != nil && manifests_path[0].to_sym == :host
expanded_path = Pathname.new(manifests_path[1]). expanded_path = Pathname.new(manifests_path[1]).
expand_path(machine.env.root_path) expand_path(machine.env.root_path)
if !expanded_path.directory? if !expanded_path.directory?
@ -99,6 +131,25 @@ module VagrantPlugins
manifest: expanded_manifest_file.to_s) manifest: expanded_manifest_file.to_s)
end end
end end
elsif environment_path != nil && environment_path[0].to_sym == :host
# Environments path/file validation
expanded_path = Pathname.new(environment_path[1]).
expand_path(machine.env.root_path)
if !expanded_path.directory?
errors << I18n.t("vagrant.provisioners.puppet.environment_path_missing",
path: expanded_path.to_s)
else
expanded_environment_file = expanded_path.join(environment)
if !expanded_environment_file.file? && !expanded_environment_file.directory?
errors << I18n.t("vagrant.provisioners.puppet.environment_missing",
environment: environment.to_s,
environment_path: expanded_path.to_s)
end
end
end
if environment_path == nil && manifests_path == nil
errors << "Please specify either a Puppet environment_path + environment (preferred) or manifests_path (deprecated)."
end end
# Module paths validation # Module paths validation
@ -108,7 +159,6 @@ module VagrantPlugins
path: path) path: path)
end end
end end
{ "puppet provisioner" => errors } { "puppet provisioner" => errors }
end end
end end

View File

@ -10,22 +10,22 @@ module VagrantPlugins
DESC DESC
config(:puppet, :provisioner) do config(:puppet, :provisioner) do
require File.expand_path("../config/puppet", __FILE__) require_relative "config/puppet"
Config::Puppet Config::Puppet
end end
config(:puppet_server, :provisioner) do config(:puppet_server, :provisioner) do
require File.expand_path("../config/puppet_server", __FILE__) require_relative "config/puppet_server"
Config::PuppetServer Config::PuppetServer
end end
provisioner(:puppet) do provisioner(:puppet) do
require File.expand_path("../provisioner/puppet", __FILE__) require_relative "provisioner/puppet"
Provisioner::Puppet Provisioner::Puppet
end end
provisioner(:puppet_server) do provisioner(:puppet_server) do
require File.expand_path("../provisioner/puppet_server", __FILE__) require_relative "provisioner/puppet_server"
Provisioner::PuppetServer Provisioner::PuppetServer
end end
end end

View File

@ -20,7 +20,6 @@ module VagrantPlugins
# Calculate the paths we're going to use based on the environment # Calculate the paths we're going to use based on the environment
root_path = @machine.env.root_path root_path = @machine.env.root_path
@expanded_module_paths = @config.expanded_module_paths(root_path) @expanded_module_paths = @config.expanded_module_paths(root_path)
@manifest_file = File.join(manifests_guest_path, @config.manifest_file)
# Setup the module paths # Setup the module paths
@module_paths = [] @module_paths = []
@ -32,13 +31,25 @@ module VagrantPlugins
folder_opts = {} folder_opts = {}
folder_opts[:type] = @config.synced_folder_type if @config.synced_folder_type folder_opts[:type] = @config.synced_folder_type if @config.synced_folder_type
folder_opts[:owner] = "root" if !@config.synced_folder_type folder_opts[:owner] = "root" if !@config.synced_folder_type
folder_opts[:args] = @config.synced_folder_args if @config.synced_folder_args
if @config.environment_path.is_a?(Array)
# Share the environments directory with the guest
if @config.environment_path[0].to_sym == :host
root_config.vm.synced_folder(
File.expand_path(@config.environment_path[1], root_path),
environments_guest_path, folder_opts)
end
end
if @config.manifest_file
@manifest_file = File.join(manifests_guest_path, @config.manifest_file)
# Share the manifests directory with the guest # Share the manifests directory with the guest
if @config.manifests_path[0].to_sym == :host if @config.manifests_path[0].to_sym == :host
root_config.vm.synced_folder( root_config.vm.synced_folder(
File.expand_path(@config.manifests_path[1], root_path), File.expand_path(@config.manifests_path[1], root_path),
manifests_guest_path, folder_opts) manifests_guest_path, folder_opts)
end end
end
# Share the module paths # Share the module paths
@module_paths.each do |from, to| @module_paths.each do |from, to|
@ -46,6 +57,24 @@ module VagrantPlugins
end end
end end
def parse_environment_metadata
# Parse out the environment manifest path since puppet apply doesnt do that for us.
environment_conf = File.join(environments_guest_path, @config.environment, "environment.conf")
if @machine.communicate.test("test -e #{environment_conf}", sudo: true)
conf = @machine.communicate.sudo("cat #{environment_conf}") do | type, data|
if type == :stdout
data.each_line do |line|
if line =~ /^\s*manifest\s+=\s+([^\s]+)/
@manifest_file = $1
@manifest_file.gsub! '$basemodulepath:', "#{environments_guest_path}/#{@config.environment}/"
@logger.debug("Using manifest from environment.conf: #{@manifest_file}")
end
end
end
end
end
end
def provision def provision
# If the machine has a wait for reboot functionality, then # If the machine has a wait for reboot functionality, then
# do that (primarily Windows) # do that (primarily Windows)
@ -53,11 +82,19 @@ module VagrantPlugins
@machine.guest.capability(:wait_for_reboot) @machine.guest.capability(:wait_for_reboot)
end end
# In environment mode we still need to specify a manifest file, if its not, use the one from env config if specified.
if !@manifest_file
@manifest_file = "#{environments_guest_path}/#{@config.environment}/manifests/site.pp"
parse_environment_metadata
end
# Check that the shared folders are properly shared # Check that the shared folders are properly shared
check = [] check = []
if @config.manifests_path[0] == :host if @config.manifests_path.is_a?(Array) && @config.manifests_path[0] == :host
check << manifests_guest_path check << manifests_guest_path
end end
if @config.environment_path.is_a?(Array) && @config.environment_path[0] == :host
check << environments_guest_path
end
@module_paths.each do |host_path, guest_path| @module_paths.each do |host_path, guest_path|
check << guest_path check << guest_path
end end
@ -71,7 +108,7 @@ module VagrantPlugins
verify_shared_folders(check) verify_shared_folders(check)
# Verify Puppet is installed and run it # Verify Puppet is installed and run it
verify_binary("puppet") verify_binary(puppet_binary_path("puppet"))
# Upload Hiera configuration if we have it # Upload Hiera configuration if we have it
@hiera_config_path = nil @hiera_config_path = nil
@ -96,13 +133,33 @@ module VagrantPlugins
end end
end end
def environments_guest_path
if config.environment_path[0] == :host
# The path is on the host, so point to where it is shared
File.join(config.temp_dir, "environments")
else
# The path is on the VM, so just point directly to it
config.environment_path[1]
end
end
# Returns the path to the Puppet binary, taking into account the
# `binary_path` configuration option.
def puppet_binary_path(binary)
return binary if !@config.binary_path
return File.join(@config.binary_path, binary)
end
def verify_binary(binary) def verify_binary(binary)
if !machine.communicate.test("sh -c 'command -v #{binary}'")
@config.binary_path = "/opt/puppetlabs/bin/"
@machine.communicate.sudo( @machine.communicate.sudo(
"which #{binary}", "test -x /opt/puppetlabs/bin/#{binary}",
error_class: PuppetError, error_class: PuppetError,
error_key: :not_detected, error_key: :not_detected,
binary: binary) binary: binary)
end end
end
def run_puppet_apply def run_puppet_apply
default_module_path = "/etc/puppet/modules" default_module_path = "/etc/puppet/modules"
@ -129,8 +186,14 @@ module VagrantPlugins
options << "--color=false" options << "--color=false"
end end
options << "--manifestdir #{manifests_guest_path}"
options << "--detailed-exitcodes" options << "--detailed-exitcodes"
if config.environment_path
options << "--environmentpath #{environments_guest_path}/"
options << "--environment #{@config.environment}"
else
options << "--manifestdir #{manifests_guest_path}"
end
options << @manifest_file options << @manifest_file
options = options.join(" ") options = options.join(" ")
@ -150,7 +213,7 @@ module VagrantPlugins
facter = "#{facts.join(" ")} " facter = "#{facts.join(" ")} "
end end
command = "#{facter}puppet apply #{options}" command = "#{facter} #{config.binary_path}puppet apply #{options}"
if config.working_directory if config.working_directory
if windows? if windows?
command = "cd #{config.working_directory}; if (`$?) \{ #{command} \}" command = "cd #{config.working_directory}; if (`$?) \{ #{command} \}"
@ -159,9 +222,15 @@ module VagrantPlugins
end end
end end
if config.environment_path
@machine.ui.info(I18n.t(
"vagrant.provisioners.puppet.running_puppet_env",
environment: config.environment))
else
@machine.ui.info(I18n.t( @machine.ui.info(I18n.t(
"vagrant.provisioners.puppet.running_puppet", "vagrant.provisioners.puppet.running_puppet",
manifest: config.manifest_file)) manifest: config.manifest_file))
end
opts = { opts = {
elevated: true, elevated: true,

View File

@ -1,11 +1,11 @@
# Salt version to install # Salt version to install
$version = '2014.1.10' $version = '2014.7.1'
# Create C:\tmp\ - if Vagrant doesn't upload keys and/or config it might not exist # Create C:\tmp\ - if Vagrant doesn't upload keys and/or config it might not exist
New-Item C:\tmp\ -ItemType directory | out-null New-Item C:\tmp\ -ItemType directory -force | out-null
# Copy minion keys & config to correct location # Copy minion keys & config to correct location
New-Item C:\salt\conf\pki\minion\ -ItemType directory | out-null New-Item C:\salt\conf\pki\minion\ -ItemType directory -force | out-null
# Check if minion keys have been uploaded # Check if minion keys have been uploaded
if (Test-Path C:\tmp\minion.pem) { if (Test-Path C:\tmp\minion.pem) {
@ -13,14 +13,9 @@ if (Test-Path C:\tmp\minion.pem) {
cp C:\tmp\minion.pub C:\salt\conf\pki\minion\ cp C:\tmp\minion.pub C:\salt\conf\pki\minion\
} }
# Check if minion config has been uploaded
if (Test-Path C:\tmp\minion) {
cp C:\tmp\minion C:\salt\conf\
}
# Detect architecture # Detect architecture
if ([IntPtr]::Size -eq 4) { if ([IntPtr]::Size -eq 4) {
$arch = "win32" $arch = "x86"
} else { } else {
$arch = "AMD64" $arch = "AMD64"
} }
@ -34,7 +29,13 @@ $webclient.DownloadFile($url, $file)
# Install minion silently # Install minion silently
Write-Host "Installing Salt minion..." Write-Host "Installing Salt minion..."
C:\tmp\salt.exe /S #Wait for process to exit before continuing...
C:\tmp\salt.exe /S | Out-Null
# Check if minion config has been uploaded
if (Test-Path C:\tmp\minion) {
cp C:\tmp\minion C:\salt\conf\
}
# Wait for salt-minion service to be registered before trying to start it # Wait for salt-minion service to be registered before trying to start it
$service = Get-Service salt-minion -ErrorAction SilentlyContinue $service = Get-Service salt-minion -ErrorAction SilentlyContinue

View File

@ -15,13 +15,17 @@ module VagrantPlugins
attr_accessor :grains_config attr_accessor :grains_config
attr_accessor :run_highstate attr_accessor :run_highstate
attr_accessor :run_overstate attr_accessor :run_overstate
attr_accessor :orchestrations
attr_accessor :always_install attr_accessor :always_install
attr_accessor :bootstrap_script attr_accessor :bootstrap_script
attr_accessor :verbose attr_accessor :verbose
attr_accessor :seed_master attr_accessor :seed_master
attr_accessor :config_dir
attr_reader :pillar_data attr_reader :pillar_data
attr_accessor :colorize attr_accessor :colorize
attr_accessor :log_level attr_accessor :log_level
attr_accessor :masterless
attr_accessor :minion_id
## bootstrap options ## bootstrap options
attr_accessor :temp_config_dir attr_accessor :temp_config_dir
@ -56,6 +60,9 @@ module VagrantPlugins
@install_syndic = UNSET_VALUE @install_syndic = UNSET_VALUE
@no_minion = UNSET_VALUE @no_minion = UNSET_VALUE
@bootstrap_options = UNSET_VALUE @bootstrap_options = UNSET_VALUE
@config_dir = UNSET_VALUE
@masterless = UNSET_VALUE
@minion_id = UNSET_VALUE
end end
def finalize! def finalize!
@ -82,7 +89,9 @@ module VagrantPlugins
@install_syndic = nil if @install_syndic == UNSET_VALUE @install_syndic = nil if @install_syndic == UNSET_VALUE
@no_minion = nil if @no_minion == UNSET_VALUE @no_minion = nil if @no_minion == UNSET_VALUE
@bootstrap_options = nil if @bootstrap_options == UNSET_VALUE @bootstrap_options = nil if @bootstrap_options == UNSET_VALUE
@config_dir = nil if @config_dir == UNSET_VALUE
@masterless = false if @masterless == UNSET_VALUE
@minion_id = nil if @minion_id == UNSET_VALUE
end end
def pillar(data) def pillar(data)
@ -90,19 +99,30 @@ module VagrantPlugins
@pillar_data = Vagrant::Util::DeepMerge.deep_merge(@pillar_data, data) @pillar_data = Vagrant::Util::DeepMerge.deep_merge(@pillar_data, data)
end end
def default_config_dir(machine)
guest_type = machine.config.vm.guest || :linux
# FIXME: there should be a way to do that a bit smarter
if guest_type == :windows
return "C:\\salt"
else
return "/etc/salt"
end
end
def validate(machine) def validate(machine)
errors = _detected_errors errors = _detected_errors
if @minion_config if @minion_config
expanded = Pathname.new(@minion_config).expand_path(machine.env.root_path) expanded = Pathname.new(@minion_config).expand_path(machine.env.root_path)
if !expanded.file? if !expanded.file?
errors << I18n.t("vagrant.provisioners.salt.minion_config_nonexist") errors << I18n.t("vagrant.provisioners.salt.minion_config_nonexist", missing_config_file: expanded)
end end
end end
if @master_config if @master_config
expanded = Pathname.new(@master_config).expand_path(machine.env.root_path) expanded = Pathname.new(@master_config).expand_path(machine.env.root_path)
if !expanded.file? if !expanded.file?
errors << I18n.t("vagrant.provisioners.salt.master_config_nonexist") errors << I18n.t("vagrant.provisioners.salt.master_config_nonexist", missing_config_file: expanded)
end end
end end
@ -129,10 +149,12 @@ module VagrantPlugins
errors << I18n.t("vagrant.provisioners.salt.must_accept_keys") errors << I18n.t("vagrant.provisioners.salt.must_accept_keys")
end end
if @config_dir.nil?
@config_dir = default_config_dir(machine)
end
return {"salt provisioner" => errors} return {"salt provisioner" => errors}
end end
end end
end end
end end

View File

@ -9,6 +9,7 @@ module VagrantPlugins
run_bootstrap_script run_bootstrap_script
call_overstate call_overstate
call_highstate call_highstate
call_orchestrate
end end
# Return a list of accepted keys # Return a list of accepted keys
@ -308,8 +309,29 @@ module VagrantPlugins
end end
end end
def call_masterless
@machine.env.ui.info "Calling state.highstate in local mode... (this may take a while)"
cmd = "salt-call state.highstate --local"
if @config.minion_id
cmd += " --id #{@config.minion_id}"
end
cmd += " -l debug#{get_pillar}"
@machine.communicate.sudo(cmd) do |type, data|
if @config.verbose
@machine.env.ui.info(data)
end
end
end
def call_highstate def call_highstate
if @config.run_highstate if @config.minion_config
@machine.env.ui.info "Copying salt minion config to #{@config.config dir}"
@machine.communicate.upload(expanded_path(@config.minion_config).to_s, @config.config_dir + "/minion")
end
if @config.masterless
call_masterless
elsif @config.run_highstate
@machine.env.ui.info "Calling state.highstate... (this may take a while)" @machine.env.ui.info "Calling state.highstate... (this may take a while)"
if @config.install_master if @config.install_master
@machine.communicate.sudo("salt '*' saltutil.sync_all") @machine.communicate.sudo("salt '*' saltutil.sync_all")
@ -340,6 +362,34 @@ module VagrantPlugins
@machine.env.ui.info "run_highstate set to false. Not running state.highstate." @machine.env.ui.info "run_highstate set to false. Not running state.highstate."
end end
end end
def call_orchestrate
if !@config.orchestrations
@machine.env.ui.info "orchestrate is nil. Not running state.orchestrate."
return
end
if !@config.install_master
@machine.env.ui.info "orchestrate does not make sense on a minion. Not running state.orchestrate."
return
end
log_output = lambda do |type, data|
if @config.verbose
@machine.env.ui.info(data)
end
end
@machine.env.ui.info "Running the following orchestrations: #{@config.orchestrations}"
@machine.env.ui.info "Running saltutil.sync_all before orchestrating"
@machine.communicate.sudo("salt '*' saltutil.sync_all", &log_output)
@config.orchestrations.each do |orchestration|
cmd = "salt-run -l info state.orchestrate #{orchestration}"
@machine.env.ui.info "Calling #{cmd}... (this may take a while)"
@machine.communicate.sudo(cmd, &log_output)
end
end
end end
end end
end end

View File

@ -10,6 +10,7 @@ module VagrantPlugins
attr_accessor :privileged attr_accessor :privileged
attr_accessor :binary attr_accessor :binary
attr_accessor :keep_color attr_accessor :keep_color
attr_accessor :name
attr_accessor :powershell_args attr_accessor :powershell_args
def initialize def initialize
@ -20,6 +21,7 @@ module VagrantPlugins
@privileged = UNSET_VALUE @privileged = UNSET_VALUE
@binary = UNSET_VALUE @binary = UNSET_VALUE
@keep_color = UNSET_VALUE @keep_color = UNSET_VALUE
@name = UNSET_VALUE
@powershell_args = UNSET_VALUE @powershell_args = UNSET_VALUE
end end
@ -31,6 +33,7 @@ module VagrantPlugins
@privileged = true if @privileged == UNSET_VALUE @privileged = true if @privileged == UNSET_VALUE
@binary = false if @binary == UNSET_VALUE @binary = false if @binary == UNSET_VALUE
@keep_color = false if @keep_color == UNSET_VALUE @keep_color = false if @keep_color == UNSET_VALUE
@name = nil if @name == UNSET_VALUE
@powershell_args = "-ExecutionPolicy Bypass" if @powershell_args == UNSET_VALUE @powershell_args = "-ExecutionPolicy Bypass" if @powershell_args == UNSET_VALUE
if @args && args_valid? if @args && args_valid?

View File

@ -65,7 +65,10 @@ module VagrantPlugins
comm.upload(path.to_s, config.upload_path) comm.upload(path.to_s, config.upload_path)
if config.path if config.name
@machine.ui.detail(I18n.t("vagrant.provisioners.shell.running",
script: "script: #{config.name}"))
elsif config.path
@machine.ui.detail(I18n.t("vagrant.provisioners.shell.running", @machine.ui.detail(I18n.t("vagrant.provisioners.shell.running",
script: path.to_s)) script: path.to_s))
else else
@ -122,7 +125,10 @@ module VagrantPlugins
command = "powershell #{shell_args.to_s} -file #{command}" if command = "powershell #{shell_args.to_s} -file #{command}" if
File.extname(exec_path).downcase == '.ps1' File.extname(exec_path).downcase == '.ps1'
if config.path if config.name
@machine.ui.detail(I18n.t("vagrant.provisioners.shell.running",
script: "script: #{config.name}"))
elsif config.path
@machine.ui.detail(I18n.t("vagrant.provisioners.shell.runningas", @machine.ui.detail(I18n.t("vagrant.provisioners.shell.runningas",
local: config.path.to_s, remote: exec_path)) local: config.path.to_s, remote: exec_path))
else else

View File

@ -74,7 +74,7 @@ module VagrantPlugins
# Create the parent directories if they does not exist (naive mkdir -p) # Create the parent directories if they does not exist (naive mkdir -p)
fullpath.descend do |path| fullpath.descend do |path|
if @server.list(path.to_s).empty? if !directory_exists?(path.to_s)
@server.mkdir(path.to_s) @server.mkdir(path.to_s)
end end
end end
@ -83,6 +83,15 @@ module VagrantPlugins
@server.putbinaryfile(local, remote) @server.putbinaryfile(local, remote)
end end
def directory_exists?(path)
begin
@server.chdir(path)
return true
rescue Net::FTPPermError
return false
end
end
private private
def pwd def pwd

View File

@ -122,13 +122,24 @@ module VagrantPlugins
machine.ui.info(I18n.t( machine.ui.info(I18n.t(
"vagrant.rsync_folder_excludes", excludes: excludes.inspect)) "vagrant.rsync_folder_excludes", excludes: excludes.inspect))
end end
if opts.include?(:verbose)
machine.ui.info(I18n.t("vagrant.rsync_showing_output"));
end
# If we have tasks to do before rsyncing, do those. # If we have tasks to do before rsyncing, do those.
if machine.guest.capability?(:rsync_pre) if machine.guest.capability?(:rsync_pre)
machine.guest.capability(:rsync_pre, opts) machine.guest.capability(:rsync_pre, opts)
end end
if opts.include?(:verbose)
command_opts[:notify] = [ :stdout, :stderr ];
r = Vagrant::Util::Subprocess.execute(*(command + [command_opts])) {
|io_name,data| data.each_line { |line| machine.ui.info("rsync[#{io_name}] -> #{line}") }
}
else
r = Vagrant::Util::Subprocess.execute(*(command + [command_opts])) r = Vagrant::Util::Subprocess.execute(*(command + [command_opts]))
end
if r.exit_code != 0 if r.exit_code != 0
raise Vagrant::Errors::RSyncError, raise Vagrant::Errors::RSyncError,
command: command.join(" "), command: command.join(" "),

View File

@ -3,3 +3,6 @@ Description='A basic static ethernet connection'
Interface=<%= options[:device] %> Interface=<%= options[:device] %>
IP=static IP=static
Address=('<%= options[:ip]%>/24') Address=('<%= options[:ip]%>/24')
<% if options[:gateway] %>
Gateway='<%= options[:gateway] %>'
<% end %>

View File

@ -4,4 +4,7 @@ auto eth<%= options[:interface] %>
iface eth<%= options[:interface] %> inet static iface eth<%= options[:interface] %> inet static
address <%= options[:ip] %> address <%= options[:ip] %>
netmask <%= options[:netmask] %> netmask <%= options[:netmask] %>
<% if options[:gateway] %>
gateway <%= options[:gateway] %>
<% end %>
#VAGRANT-END #VAGRANT-END

View File

@ -6,7 +6,11 @@ ONBOOT=yes
IPADDR=<%= options[:ip] %> IPADDR=<%= options[:ip] %>
NETMASK=<%= options[:netmask] %> NETMASK=<%= options[:netmask] %>
DEVICE=<%= options[:device] %> DEVICE=<%= options[:device] %>
<%= options[:gateway] ? "GATEWAY=#{options[:gateway]}" : '' %> <% if options[:gateway] %>
<%= options[:mac_address] ? "HWADDR=#{options[:mac_address]}" : '' %> GATEWAY=<%= options[:gateway] %>
<% end %>
<% if options[:mac_address] %>
HWADDR=<%= options[:mac_address] %>
<% end %>
PEERDNS=no PEERDNS=no
#VAGRANT-END #VAGRANT-END

View File

@ -1,3 +1,6 @@
#VAGRANT-BEGIN #VAGRANT-BEGIN
ifconfig_<%= ifname %>="inet <%= options[:ip] %> netmask <%= options[:netmask] %>" ifconfig_<%= ifname %>="inet <%= options[:ip] %> netmask <%= options[:netmask] %>"
<% if options[:gateway] %>
default_router="<%= options[:gateway] %>"
<% end %>
#VAGRANT-END #VAGRANT-END

View File

@ -2,5 +2,9 @@
# The contents below are automatically generated by Vagrant. Do not modify. # The contents below are automatically generated by Vagrant. Do not modify.
template='interface' template='interface'
ipaddr='<%= options[:ip] %>/<%= options[:netmask] %>' ipaddr='<%= options[:ip] %>/<%= options[:netmask] %>'
<%= [:gateway, :nameservers, :domain, :route, :gateway6, :route6, :mtu].reduce([]) { |a,i| a.push("#{i}=#{options[i]}") if options[i]; a }.join("\n") %> <% [:gateway, :nameservers, :domain, :route, :gateway6, :route6, :mtu].each do |key| %>
<% if options[key] %>
<%= key %>='<%= options[key] %>'
<% end %>
<% end %>
#VAGRANT-END #VAGRANT-END

View File

@ -1,4 +1,7 @@
#VAGRANT-BEGIN #VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify. # The contents below are automatically generated by Vagrant. Do not modify.
config_eth<%= options[:interface] %>=("<%= options[:ip] %> netmask <%= options[:netmask] %>") config_eth<%= options[:interface] %>=("<%= options[:ip] %> netmask <%= options[:netmask] %>")
<% if options[:gateway] %>
gateways_eth<%= options[:interface] %>="<%= options[:gateway] %>"
<% end %>
#VAGRANT-END #VAGRANT-END

View File

@ -6,5 +6,8 @@ ONBOOT=yes
IPADDR=<%= options[:ip] %> IPADDR=<%= options[:ip] %>
NETMASK=<%= options[:netmask] %> NETMASK=<%= options[:netmask] %>
DEVICE=eth<%= options[:interface] %> DEVICE=eth<%= options[:interface] %>
<% if options[:gateway] %>
GATEWAY=<%= options[:gateway] %>
<% end %>
PEERDNS=no PEERDNS=no
#VAGRANT-END #VAGRANT-END

View File

@ -4,7 +4,10 @@ BOOTPROTO='static'
IPADDR='<%= options[:ip] %>' IPADDR='<%= options[:ip] %>'
NETMASK='<%= options[:netmask] %>' NETMASK='<%= options[:netmask] %>'
DEVICE='eth<%= options[:interface] %>' DEVICE='eth<%= options[:interface] %>'
PEERDNS=no <% if options[:gateway] %>
GATEWAY='<%= options[:gateway] %>'
<% end %>
PEERDNS='no'
STARTMODE='auto' STARTMODE='auto'
USERCONTROL='no' USERCONTROL='no'
#VAGRANT-END #VAGRANT-END

View File

@ -24,6 +24,8 @@ en:
Downloading: %{url} Downloading: %{url}
box_download_error: |- box_download_error: |-
Error downloading: %{message} Error downloading: %{message}
box_unpacking: |-
Unpacking necessary files from: %{url}
box_expanding_url: |- box_expanding_url: |-
URL: %{url} URL: %{url}
box_loading_metadata: |- box_loading_metadata: |-
@ -212,6 +214,7 @@ en:
The provider ('%{provider}') for the machine '%{name}' is The provider ('%{provider}') for the machine '%{name}' is
using a proxy machine. RSync will sync to this proxy using a proxy machine. RSync will sync to this proxy
instead of directly to the environment itself. instead of directly to the environment itself.
rsync_showing_output: "Showing rsync output..."
rsync_ssh_password: |- rsync_ssh_password: |-
The machine you're rsyncing folders to is configured to use The machine you're rsyncing folders to is configured to use
password-based authentication. Vagrant can't script rsync to automatically password-based authentication. Vagrant can't script rsync to automatically
@ -285,7 +288,7 @@ en:
id_in_pre_import: |- id_in_pre_import: |-
The ':id' parameter is not available in "pre-import" customizations. The ':id' parameter is not available in "pre-import" customizations.
intnet_on_bad_type: |- intnet_on_bad_type: |-
VirtualBox internal networks can only be enabled on "private_networks" VirtualBox internal networks can only be enabled on "private_network"
invalid_event: |- invalid_event: |-
%{event} is not a valid event for customization. Valid events %{event} is not a valid event for customization. Valid events
are: %{valid_events} are: %{valid_events}
@ -1197,7 +1200,8 @@ en:
a syntax error. a syntax error.
Path: %{path} Path: %{path}
Message: %{message} Line number: %{line}
Message: %{exception_class}: %{message}
vagrantfile_syntax_error: |- vagrantfile_syntax_error: |-
There is a syntax error in the following Vagrantfile. The syntax error There is a syntax error in the following Vagrantfile. The syntax error
message is reproduced below for convenience: message is reproduced below for convenience:
@ -1696,10 +1700,10 @@ en:
provision: provision:
beginning: "Running provisioner: %{provisioner}..." beginning: "Running provisioner: %{provisioner}..."
disabled_by_config: |- disabled_by_config: |-
Machine not provisioning because `--no-provision` is specified. Machine not provisioned because `--no-provision` is specified.
disabled_by_sentinel: |- disabled_by_sentinel: |-
Machine already provisioned. Run `vagrant provision` or use the `--provision` Machine already provisioned. Run `vagrant provision` or use the `--provision`
to force provisioning. Provisioners marked to run always will still run. flag to force provisioning. Provisioners marked to run always will still run.
resume: resume:
resuming: Resuming suspended VM... resuming: Resuming suspended VM...
unpausing: |- unpausing: |-
@ -1749,7 +1753,7 @@ en:
packaging: "Packaging additional file: %{file}" packaging: "Packaging additional file: %{file}"
compressing: "Compressing package to: %{tar_path}" compressing: "Compressing package to: %{tar_path}"
output_exists: |- output_exists: |-
The specified file to save the package as already exists. Please The specified file '%{file_name}' to save the package as already exists. Please
remove this file or specify a different file name for outputting. remove this file or specify a different file name for outputting.
output_is_directory: |- output_is_directory: |-
The specified output is a directory. Please specify a path including The specified output is a directory. Please specify a path including
@ -1852,11 +1856,17 @@ en:
installed on this guest. Puppet provisioning can not continue without installed on this guest. Puppet provisioning can not continue without
Puppet properly installed. Puppet properly installed.
running_puppet: "Running Puppet with %{manifest}..." running_puppet: "Running Puppet with %{manifest}..."
running_puppet_env: "Running Puppet with environment %{environment}..."
manifest_missing: |- manifest_missing: |-
The configured Puppet manifest is missing. Please specify a path to an The configured Puppet manifest is missing. Please specify a path to an
existing manifest: existing manifest:
%{manifest} %{manifest}
environment_missing: |-
The configured Puppet environment folder %{environment} was not found in the
specified environmentpath %{environmentpath}.
Please specify a path to an existing Puppet directory environment.
environment_path_missing: "The environment path specified for Puppet does not exist: %{path}"
manifests_path_missing: "The manifests path specified for Puppet does not exist: %{path}" manifests_path_missing: "The manifests path specified for Puppet does not exist: %{path}"
missing_shared_folders: |- missing_shared_folders: |-
Shared folders that Puppet requires are missing on the virtual machine. Shared folders that Puppet requires are missing on the virtual machine.
@ -1908,9 +1918,9 @@ en:
salt: salt:
minion_config_nonexist: |- minion_config_nonexist: |-
The specified minion_config file could not be found. The specified minion_config '%{missing_config_file}' file could not be found.
master_config_nonexist: |- master_config_nonexist: |-
The specified master_config file could not be found. The specified master_config '%{missing_config_file}' file could not be found.
grains_config_nonexist: |- grains_config_nonexist: |-
The specified grains_config file could not be found. The specified grains_config file could not be found.
missing_key: |- missing_key: |-

View File

@ -0,0 +1,44 @@
require File.expand_path("../../../../../base", __FILE__)
describe "VagrantPlugins::GuestLinux::Cap::MountSharedFolder" do
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:guest) { double("guest") }
before do
allow(machine).to receive(:guest).and_return(guest)
allow(machine).to receive(:communicate).and_return(communicator)
allow(guest).to receive(:capability).and_return(nil)
end
describe "smb" do
let(:described_class) do
VagrantPlugins::GuestLinux::Plugin.components.guest_capabilities[:linux].get(:mount_smb_shared_folder)
end
describe ".mount_shared_folder" do
describe "with a domain" do
let(:mount_command) { "mount -t cifs -o uid=`id -u `,gid=`getent group | cut -d: -f3`,sec=ntlm,username=user,pass=pass,domain=domain //host/name " }
before do
communicator.expect_command mount_command
communicator.stub_command mount_command, exit_code: 0
end
after { communicator.verify_expectations! }
it "should call mount with correct args" do
described_class.mount_smb_shared_folder(machine, 'name', 'guestpath', {:smb_username => "user@domain", :smb_password => "pass", :smb_host => "host"})
end
end
describe "without a domain" do
let(:mount_command) { "mount -t cifs -o uid=`id -u `,gid=`getent group | cut -d: -f3`,sec=ntlm,username=user,pass=pass //host/name " }
before do
communicator.expect_command mount_command
communicator.stub_command mount_command, exit_code: 0
end
after { communicator.verify_expectations! }
it "should call mount with correct args" do
described_class.mount_smb_shared_folder(machine, 'name', 'guestpath', {:smb_username => "user", :smb_password => "pass", :smb_host => "host"})
end
end
end
end
end

View File

@ -0,0 +1,34 @@
# encoding: UTF-8
# Copyright (c) 2015 VMware, Inc. All Rights Reserved.
require File.expand_path("../../../../../base", __FILE__)
describe "VagrantPlugins::GuestPhoton::Cap::ChangeHostName" do
let(:described_class) do
VagrantPlugins::GuestPhoton::Plugin.components.guest_capabilities[:photon].get(:change_host_name)
end
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
end
after do
communicator.verify_expectations!
end
it 'should change hostname when hostname is differ from current' do
hostname = 'vagrant-photon'
expect(communicator).to receive(:test).with("sudo hostname --fqdn | grep 'vagrant-photon'")
communicator.should_receive(:sudo).with("hostname #{hostname.split('.')[0]}")
described_class.change_host_name(machine, hostname)
end
it 'should not change hostname when hostname equals current' do
hostname = 'vagrant-photon'
communicator.stub(:test).and_return(true)
communicator.should_not_receive(:sudo)
described_class.change_host_name(machine, hostname)
end
end

View File

@ -0,0 +1,40 @@
# encoding: UTF-8
# Copyright (c) 2015 VMware, Inc. All Rights Reserved.
require File.expand_path("../../../../../base", __FILE__)
describe "VagrantPlugins::GuestPhoton::Cap::ConfigureNetworks" do
let(:described_class) do
VagrantPlugins::GuestPhoton::Plugin.components.guest_capabilities[:photon].get(:configure_networks)
end
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
before do
allow(machine).to receive(:communicate).and_return(communicator)
end
after do
communicator.verify_expectations!
end
it 'should configure networks' do
networks = [
{ :type => :static, :ip => '192.168.10.10', :netmask => '255.255.255.0', :interface => 1, :name => 'eth0' },
{ :type => :dhcp, :interface => 2, :name => 'eth1' },
{ :type => :static, :ip => '10.168.10.10', :netmask => '255.255.0.0', :interface => 3, :name => 'docker0' }
]
communicator.should_receive(:sudo).with("ifconfig | grep 'eth' | cut -f1 -d' '")
communicator.should_receive(:sudo).with('ifconfig 192.168.10.10 netmask 255.255.255.0')
communicator.should_receive(:sudo).with('ifconfig netmask ')
communicator.should_receive(:sudo).with('ifconfig 10.168.10.10 netmask 255.255.0.0')
allow_message_expectations_on_nil
machine.should_receive(:env).at_least(5).times
machine.env.should_receive(:active_machines).at_least(:twice)
machine.env.active_machines.should_receive(:first)
machine.env.should_receive(:machine)
described_class.configure_networks(machine, networks)
end
end

View File

@ -0,0 +1,26 @@
# encoding: UTF-8
# Copyright (c) 2015 VMware, Inc. All Rights Reserved.
require File.expand_path("../../../../../base", __FILE__)
describe "VagrantPlugins::GuestPhoton::Cap::Docker" do
let(:described_class) do
VagrantPlugins::GuestPhoton::Plugin.components.guest_capabilities[:photon].get(:docker_daemon_running)
end
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:old_hostname) { 'oldhostname.olddomain.tld' }
before do
allow(machine).to receive(:communicate).and_return(communicator)
end
after do
communicator.verify_expectations!
end
it 'should check docker' do
expect(communicator).to receive(:test).with('test -S /run/docker.sock')
described_class.docker_daemon_running(machine)
end
end

View File

@ -0,0 +1,26 @@
require File.expand_path("../../../../../base", __FILE__)
describe "VagrantPlugins::GuestTinyCore::Cap::ChangeHostName" do
let(:described_class) do
VagrantPlugins::GuestTinyCore::Plugin.components.guest_capabilities[:tinycore].get(:change_host_name)
end
let(:machine) { double("machine") }
let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
let(:old_hostname) { 'boot2docker' }
before do
allow(machine).to receive(:communicate).and_return(communicator)
communicator.stub_command('hostname -f', stdout: old_hostname)
end
after do
communicator.verify_expectations!
end
describe ".change_host_name" do
it "refreshes the hostname service with the sethostname command" do
communicator.expect_command(%q(/usr/bin/sethostname newhostname.newdomain.tld))
described_class.change_host_name(machine, 'newhostname.newdomain.tld')
end
end
end

View File

@ -14,6 +14,15 @@ describe VagrantPlugins::HyperV::Config do
expect(subject.ip_address_timeout).to eq(120) expect(subject.ip_address_timeout).to eq(120)
end end
end end
describe "#vlan_id" do
it "can be set" do
subject.vlan_id = 100
subject.finalize!
expect(subject.vlan_id).to eq(100)
end
end
describe "#vmname" do describe "#vmname" do
it "can be set" do it "can be set" do
subject.vmname = "test" subject.vmname = "test"
@ -21,6 +30,7 @@ describe VagrantPlugins::HyperV::Config do
expect(subject.vmname).to eq("test") expect(subject.vmname).to eq("test")
end end
end end
describe "#memory" do describe "#memory" do
it "can be set" do it "can be set" do
subject.memory = 512 subject.memory = 512
@ -28,6 +38,7 @@ describe VagrantPlugins::HyperV::Config do
expect(subject.memory).to eq(512) expect(subject.memory).to eq(512)
end end
end end
describe "#maxmemory" do describe "#maxmemory" do
it "can be set" do it "can be set" do
subject.maxmemory = 1024 subject.maxmemory = 1024
@ -35,6 +46,7 @@ describe VagrantPlugins::HyperV::Config do
expect(subject.maxmemory).to eq(1024) expect(subject.maxmemory).to eq(1024)
end end
end end
describe "#cpus" do describe "#cpus" do
it "can be set" do it "can be set" do
subject.cpus = 2 subject.cpus = 2

View File

@ -56,6 +56,10 @@ VF
machine.stub(ssh_info: ssh_info) machine.stub(ssh_info: ssh_info)
machine.env.stub(active_machines: [[iso_env.machine_names[0], :dummy], [iso_env.machine_names[1], :dummy]]) machine.env.stub(active_machines: [[iso_env.machine_names[0], :dummy], [iso_env.machine_names[1], :dummy]])
stubbed_ui = Vagrant::UI::Colored.new
stubbed_ui.stub(detail: "")
machine.env.stub(ui: stubbed_ui)
config.playbook = 'playbook.yml' config.playbook = 'playbook.yml'
end end
@ -111,6 +115,7 @@ VF
end end
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentitiesOnly=yes") expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentitiesOnly=yes")
expect(cmd_opts[:env]['ANSIBLE_FORCE_COLOR']).to eql("true") expect(cmd_opts[:env]['ANSIBLE_FORCE_COLOR']).to eql("true")
expect(cmd_opts[:env]).to_not include("ANSIBLE_NOCOLOR")
expect(cmd_opts[:env]['ANSIBLE_HOST_KEY_CHECKING']).to eql(expected_host_key_checking.to_s) expect(cmd_opts[:env]['ANSIBLE_HOST_KEY_CHECKING']).to eql(expected_host_key_checking.to_s)
expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1) expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1)
} }
@ -468,7 +473,7 @@ VF
it "shows the ansible-playbook command" do it "shows the ansible-playbook command" do
expect(machine.env.ui).to receive(:detail).with { |full_command| expect(machine.env.ui).to receive(:detail).with { |full_command|
expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml") expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_FORCE_COLOR=true ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml")
} }
end end
end end
@ -483,7 +488,21 @@ VF
it "shows the ansible-playbook command" do it "shows the ansible-playbook command" do
expect(machine.env.ui).to receive(:detail).with { |full_command| expect(machine.env.ui).to receive(:detail).with { |full_command|
expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml") expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_FORCE_COLOR=true ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml")
}
end
end
describe "without colorized output" do
before do
machine.env.stub(ui: Vagrant::UI::Basic.new)
end
it "disables ansible-playbook colored output" do
expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args|
cmd_opts = args.last
expect(cmd_opts[:env]).to_not include("ANSIBLE_FORCE_COLOR")
expect(cmd_opts[:env]['ANSIBLE_NOCOLOR']).to eql("true")
} }
end end
end end
@ -541,7 +560,7 @@ VF
it "shows the ansible-playbook command, with additional quotes when required" do it "shows the ansible-playbook command, with additional quotes when required" do
expect(machine.env.ui).to receive(:detail).with { |full_command| expect(machine.env.ui).to receive(:detail).with { |full_command|
expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --timeout=30 --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' playbook.yml") expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_FORCE_COLOR=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --timeout=30 --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' playbook.yml")
} }
end end
end end

View File

@ -0,0 +1,19 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/arch/network_dhcp" do
let(:template) { "guests/arch/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
Description='A basic dhcp ethernet connection'
Interface=en0
Connection=ethernet
IP=dhcp
EOH
end
end

View File

@ -0,0 +1,37 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/arch/network_static" do
let(:template) { "guests/arch/network_static" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
Connection=ethernet
Description='A basic static ethernet connection'
Interface=en0
IP=static
Address=('1.1.1.1/24')
EOH
end
it "includes the gateway" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
gateway: "1.2.3.4",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
Connection=ethernet
Description='A basic static ethernet connection'
Interface=en0
IP=static
Address=('1.1.1.1/24')
Gateway='1.2.3.4'
EOH
end
end

View File

@ -0,0 +1,41 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/debian/network_dhcp" do
let(:template) { "guests/debian/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
auto eth
iface eth inet dhcp
post-up route del default dev $IFACE || true
#VAGRANT-END
EOH
end
context "when use_dhcp_assigned_default_route is set" do
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
use_dhcp_assigned_default_route: true,
})
expect(result).to eq <<-EOH.gsub(/^ {8}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
auto eth
iface eth inet dhcp
# We need to disable eth0, see GH-2648
post-up route del default dev eth0
post-up dhclient $IFACE
pre-down route add default dev eth0
#VAGRANT-END
EOH
end
end
end

View File

@ -0,0 +1,43 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/debian/network_static" do
let(:template) { "guests/debian/network_static" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
auto eth
iface eth inet static
address 1.1.1.1
netmask 255.255.0.0
#VAGRANT-END
EOH
end
it "includes the gateway" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
gateway: "1.2.3.4",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
auto eth
iface eth inet static
address 1.1.1.1
netmask 255.255.0.0
gateway 1.2.3.4
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,21 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/fedora/network_dhcp" do
let(:template) { "guests/fedora/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
BOOTPROTO=dhcp
ONBOOT=yes
DEVICE=en0
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,71 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/fedora/network_static" do
let(:template) { "guests/fedora/network_static" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
NM_CONTROLLED=no
BOOTPROTO=none
ONBOOT=yes
IPADDR=1.1.1.1
NETMASK=255.255.0.0
DEVICE=en0
PEERDNS=no
#VAGRANT-END
EOH
end
it "includes the gateway" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
gateway: "1.2.3.4",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
NM_CONTROLLED=no
BOOTPROTO=none
ONBOOT=yes
IPADDR=1.1.1.1
NETMASK=255.255.0.0
DEVICE=en0
GATEWAY=1.2.3.4
PEERDNS=no
#VAGRANT-END
EOH
end
it "includes the mac_address" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
mac_address: "abcd1234",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
NM_CONTROLLED=no
BOOTPROTO=none
ONBOOT=yes
IPADDR=1.1.1.1
NETMASK=255.255.0.0
DEVICE=en0
HWADDR=abcd1234
PEERDNS=no
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,16 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/freebsd/network_dhcp" do
let(:template) { "guests/freebsd/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, ifname: "vtneten0")
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
ifconfig_vtneten0="DHCP"
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,39 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/freebsd/network_static" do
let(:template) { "guests/freebsd/network_static" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template,
ifname: "vtneten0",
options: {
ip: "1.1.1.1",
netmask: "255.255.0.0",
},
)
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
ifconfig_vtneten0="inet 1.1.1.1 netmask 255.255.0.0"
#VAGRANT-END
EOH
end
it "includes the gateway" do
result = Vagrant::Util::TemplateRenderer.render(template,
ifname: "vtneten0",
options: {
ip: "1.1.1.1",
netmask: "255.255.0.0",
gateway: "1.2.3.4",
},
)
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
ifconfig_vtneten0="inet 1.1.1.1 netmask 255.255.0.0"
default_router="1.2.3.4"
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,19 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/funtoo/network_dhcp" do
let(:template) { "guests/funtoo/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='dhcp'
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,141 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/funtoo/network_static" do
let(:template) { "guests/funtoo/network_static" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
#VAGRANT-END
EOH
end
it "includes the gateway" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
gateway: "1.2.3.4",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
gateway='1.2.3.4'
#VAGRANT-END
EOH
end
it "includes the nameservers" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
nameservers: "ns1.company.com",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
nameservers='ns1.company.com'
#VAGRANT-END
EOH
end
it "includes the domain" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
domain: "company.com",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
domain='company.com'
#VAGRANT-END
EOH
end
it "includes the route" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
route: "5.6.7.8",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
route='5.6.7.8'
#VAGRANT-END
EOH
end
it "includes the gateway6" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
gateway6: "aaaa:0000",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
gateway6='aaaa:0000'
#VAGRANT-END
EOH
end
it "includes the route6" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
route6: "bbbb:1111",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
route6='bbbb:1111'
#VAGRANT-END
EOH
end
it "includes the mtu" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
device: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
mtu: "1",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
template='interface'
ipaddr='1.1.1.1/255.255.0.0'
mtu='1'
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,19 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/gentoo/network_dhcp" do
let(:template) { "guests/gentoo/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
interface: "en0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
config_ethen0="dhcp"
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,37 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/gentoo/network_static" do
let(:template) { "guests/gentoo/network_static" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
interface: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
config_ethen0=("1.1.1.1 netmask 255.255.0.0")
#VAGRANT-END
EOH
end
it "includes the gateway" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
interface: "en0",
ip: "1.1.1.1",
netmask: "255.255.0.0",
gateway: "1.2.3.4",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
# The contents below are automatically generated by Vagrant. Do not modify.
config_ethen0=("1.1.1.1 netmask 255.255.0.0")
gateways_ethen0="1.2.3.4"
#VAGRANT-END
EOH
end
end

View File

@ -0,0 +1,18 @@
require_relative "../../../base"
require "vagrant/util/template_renderer"
describe "templates/guests/netbsd/network_dhcp" do
let(:template) { "guests/netbsd/network_dhcp" }
it "renders the template" do
result = Vagrant::Util::TemplateRenderer.render(template, options: {
interface: "en0",
})
expect(result).to eq <<-EOH.gsub(/^ {6}/, "")
#VAGRANT-BEGIN
ifconfig_wmen0=dhcp
#VAGRANT-END
EOH
end
end

Some files were not shown because too many files have changed in this diff Show More