merge with upstream master / fix conflickt in layout
This commit is contained in:
commit
b98db9ce59
|
@ -1,6 +1,10 @@
|
|||
# OS-specific
|
||||
.DS_Store
|
||||
|
||||
# Editor swapfiles
|
||||
.*.sw?
|
||||
*~
|
||||
|
||||
# Vagrant stuff
|
||||
acceptance_config.yml
|
||||
boxes/*
|
||||
|
|
140
CHANGELOG.md
140
CHANGELOG.md
|
@ -2,22 +2,162 @@
|
|||
|
||||
FEATURES:
|
||||
|
||||
- **New Command: `vagrant powershell`**: For machines that support it,
|
||||
this will open a PowerShell prompt.
|
||||
- **New Command: `vagrant port`**: For machines that support it, this will
|
||||
display the list of forwarded ports from the guest to the host.
|
||||
- **Linked Clones**: VirtualBox and VMware providers now support
|
||||
linked clones for very fast (millisecond) imports on up. [GH-4484]
|
||||
- **Snapshots**: The `vagrant snapshot` command can be used to checkpoint
|
||||
and restore point-in-time snapshots.
|
||||
- **IPv6 Private Networks**: Private networking now supports IPv6. This
|
||||
only works with VirtualBox and VMware at this point. [GH-6342]
|
||||
- New provisioner: `ansible_local` to execute Ansible from the guest
|
||||
machine. [GH-2103]
|
||||
|
||||
BREAKING CHANGES:
|
||||
|
||||
- The `ansible` provisioner now can override the effective ansible remote user
|
||||
(i.e. `ansible_ssh_user` setting) to always correspond to the vagrant ssh
|
||||
username. This change is enabled by default, but we expect this to affect
|
||||
only a tiny number of people as it corresponds to the common usage.
|
||||
If you however use multiple remote usernames in your Ansible plays, tasks,
|
||||
or custom inventories, you can simply set the option `force_remote_user` to
|
||||
false to make Vagrant behave the same as before.
|
||||
- provisioners/salt: the "config_dir" option has been removed. It has no
|
||||
effect in Vagrant 1.8. [GH-6073]
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
||||
- core: allow removal of all box versions with `--all` flag [GH-3462]
|
||||
- core: prune entries from global status on non-existent cwd [GH-6535]
|
||||
- core: networking: allow specifying a DHCP IP [GH-6325]
|
||||
- core: run provisioner cleanup tasks before powering off the VM [GH-6553]
|
||||
- core: only run provisioner cleanup tasks if they're implemented [GH-6603]
|
||||
This improves UX, but wasn't a bug before.
|
||||
- command/plugin: Add `--plugin-clean-sources` flag to reset plugin install
|
||||
sources, primarily for corp firewalls. [GH-4738]
|
||||
- command/rsync-auto: SSH connection is cached for faster sync times [GH-6399]
|
||||
- command/up: provisioners are run on suspend resume [GH-5815]
|
||||
- communicators/ssh: allow specifying host environment variables to forward
|
||||
to guests [GH-4132, GH-6562]
|
||||
- communicators/winrm: Configurable execution time limit [GH-6213]
|
||||
- providers/virtualbox: cache version lookup, which caused significant
|
||||
slowdown on some Windows hosts [GH-6552]
|
||||
- providers/virtualbox: add `public_address` capability for virtualbox
|
||||
[GH-6583, GH-5978]
|
||||
- provisioners/chef: perform cleanup tasks on the guest instead of the host
|
||||
- provisioners/chef: automatically generate a node_name if one was not given
|
||||
[GH-6555]
|
||||
- provisioners/chef: install Chef automatically on Windows [GH-6557]
|
||||
- provisioners/chef: allow the user to specify the Chef product (such as
|
||||
the Chef Development Kit) [GH-6557]
|
||||
- provisioners/chef: allow data_bags_path to be an array [GH-5988, GH-6561]
|
||||
- provisioners/shell: Support interactive mode for elevated PowerShell
|
||||
scripts [GH-6185]
|
||||
- provisioners/shell: add `env` option [GH-6588, GH-6516]
|
||||
- provisioners/ansible+ansible_local: add support for ansible-galaxy [GH-2718]
|
||||
- provisioners/ansible+ansible_local: add support for group and host variables
|
||||
in the generated inventory [GH-6619]
|
||||
- provisioners/ansible+ansible_local: add support for alphanumeric patterns
|
||||
for groups in the generated inventory [GH-3539]
|
||||
- provisioners/ansible: add support for WinRM settings [GH-5086]
|
||||
- provisioners/ansible: add new `force_remote_user` option to control whether
|
||||
`ansible_ssh_user` parameter should be applied or not [GH-6348]
|
||||
- provisioners/ansible: show a warning when running from a Windows Host [GH-5292]
|
||||
- pushes/local-exec: add support for specifying script args [GH-6661, GH-6660]
|
||||
- guests/slackware: add support for networking [GH-6514]
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
- core: Ctrl-C weirdness fixed where it would exit parent process
|
||||
before Vagrant finished cleaning up [GH-6085]
|
||||
- core: DHCP network configurations don't warn on IP addresses ending
|
||||
in ".1" [GH-6150]
|
||||
- core: only append `access_token` when it does not exist in the URL
|
||||
[GH-6395, GH-6534]
|
||||
- core: use the correct private key when packaging a box [GH-6406]
|
||||
- core: fix crash when using invalid box checksum type [GH-6327]
|
||||
- core: don't check for metadata if the download URL is not HTTP [GH-6540]
|
||||
- core: don't make custom dotfile path if there is no Vagrantfile [GH-6542]
|
||||
- core: more robust check for admin privs on Windows [GH-5616]
|
||||
- core: properly detect when HTTP server doesn't support byte ranges and
|
||||
retry from scratch [GH-4479]
|
||||
- core: line numbers show properly in Vagrantfile syntax errors
|
||||
on Windows [GH-6445]
|
||||
- core: catch errors setting env vars on Windows [GH-6017]
|
||||
- core: remove cached synced folders when they're removed from the
|
||||
Vagrantfile [GH-6567]
|
||||
- core: use case-insensitive comparison for box checksum validations
|
||||
[GH-6648, GH-6650]
|
||||
- commands/box: add command with `~` paths on Windows works [GH-5747]
|
||||
- commands/box: the update command supports CA settings [GH-4473]
|
||||
- commands/box: removing all versions and providers of a box will properly
|
||||
clean all directories in `~/.vagrant.d/boxes` [GH-3570]
|
||||
- commands/box: outdated global won't halt on metadata download failure [GH-6453]
|
||||
- commands/login: respect environment variables in `vagrant login` command
|
||||
[GH-6590, GH-6422]
|
||||
- commands/package: when re-packaging a packaged box, preserve the
|
||||
generated SSH key [GH-5780]
|
||||
- commands/plugin: retry plugin install automatically a few times to
|
||||
avoid network issues [GH-6097]
|
||||
- commands/rdp: prefer `xfreerdp` if it is available on Linux [GH-6475]
|
||||
- commands/up: the `--provision-with` flag works with provisioner names [GH-5981]
|
||||
- communicator/ssh: fix potential crash case with PTY [GH-6225]
|
||||
- communicator/ssh: escape IdentityFile path [GH-6428, GH-6589]
|
||||
- communicator/winrm: respect `boot_timeout` setting [GH-6229]
|
||||
- communicator/winrm: execute scheduled tasks immediately on Windows XP
|
||||
since elevation isn't required [GH-6195]
|
||||
- communicator/winrm: Decouple default port forwarding rules for "winrm" and
|
||||
"winrm-ssl" [GH-6581]
|
||||
- communicator/winrm: Hide progress bars from PowerShell v5 [GH-6309]
|
||||
- guests/arch: enable network device after setting it up [GH-5737]
|
||||
- guests/darwin: advanced networking works with more NICs [GH-6386]
|
||||
- guests/debian: graceful shutdown works properly with newer releases [GH-5986]
|
||||
- guests/fedora: Preserve `localhost` entry when changing hostname [GH-6203]
|
||||
- guests/fedora: Use dnf if it is available [GH-6288]
|
||||
- guests/linux: when replacing a public SSH key, use POSIX-compliant
|
||||
sed flags [GH-6565]
|
||||
- guests/suse: DHCP network interfaces properly configured [GH-6502]
|
||||
- hosts/slackware: Better detection of NFS [GH-6367]
|
||||
- providers/hyper-v: support generation 2 VMs [GH-6372]
|
||||
- providers/hyper-v: support VMs with more than one NIC [GH-4346]
|
||||
- providers/hyper-v: check if user is in the Hyper-V admin group if
|
||||
they're not a Windows admin [GH-6662]
|
||||
- providers/virtualbox: ignore "Unknown" status bridge interfaces [GH-6061]
|
||||
- providers/virtualbox: only fix ipv6 interfaces that are in use
|
||||
[GH-6586, GH-6552]
|
||||
- provisioners/ansible: use quotes for the `ansible_ssh_private_key_file`
|
||||
value in the generated inventory [GH-6209]
|
||||
- provisioners/ansible: use quotes when passing the private key files via
|
||||
OpenSSH `-i` command line arguments [GH-6671]
|
||||
- provisioners/ansible: don't show the `ansible-playbook` command when verbose
|
||||
option is an empty string
|
||||
- provisioners/chef: fix `nodes_path` for Chef Zero [GH-6025, GH-6049]
|
||||
- provisioners/chef: do not error when the `node_name` is unset
|
||||
[GH-6005, GH-6064, GH-6541]
|
||||
- provisioners/chef: only force the formatter on Chef 11 or higher
|
||||
[GH-6278, GH-6556]
|
||||
- provisioners/chef: require `nodes_path` to be set for Chef Zero
|
||||
[GH-6110, GH-6559]
|
||||
- provisioners/puppet: apply provisioner uses correct default manifests
|
||||
with environments. [GH-5987]
|
||||
- provisioners/puppet: remove broken backticks [GH-6404]
|
||||
- provisioners/puppet: find Puppet binary properly on Windows [GH-6259]
|
||||
- provisioners/puppet-server: works with Puppet Collection 1 [GH-6389]
|
||||
- provisioners/salt: call correct executables on Windows [GH-5999]
|
||||
- provisioners/salt: log level and colorize works for masterless [GH-6474]
|
||||
- push/local-exec: use subprocess on windows when fork does not exist
|
||||
[GH-5307, GH-6563]
|
||||
- push/heroku: use current branch [GH-6554]
|
||||
- synced\_folders/rsync: on Windows, replace all paths with Cygwin
|
||||
paths since all rsync implementations require this [GH-6160]
|
||||
- synced\_folders/smb: use credentials files to allow for more characters
|
||||
in password [GH-4230]
|
||||
|
||||
PLUGIN AUTHOR CHANGES:
|
||||
|
||||
- installer: Upgrade to Ruby 2.2.3
|
||||
|
||||
## 1.7.4 (July 17, 2015)
|
||||
|
||||
|
|
10
README.md
10
README.md
|
@ -1,6 +1,6 @@
|
|||
# Vagrant
|
||||
|
||||
* Website: [http://www.vagrantup.com](http://www.vagrantup.com)
|
||||
* Website: [https://www.vagrantup.com/](https://www.vagrantup.com/)
|
||||
* Source: [https://github.com/mitchellh/vagrant](https://github.com/mitchellh/vagrant)
|
||||
* IRC: `#vagrant` on Freenode
|
||||
* Mailing list: [Google Groups](http://groups.google.com/group/vagrant-up)
|
||||
|
@ -19,12 +19,12 @@ between Windows, Mac OS X, and Linux.
|
|||
## Quick Start
|
||||
|
||||
For the quick-start, we'll bring up a development machine on
|
||||
[VirtualBox](http://www.virtualbox.org) because it is free and works
|
||||
[VirtualBox](https://www.virtualbox.org/) because it is free and works
|
||||
on all major platforms. Vagrant can, however, work with almost any
|
||||
system such as OpenStack, VMware, Docker, etc.
|
||||
system such as [OpenStack] (https://www.openstack.org/), [VMware] (http://www.vmware.com/), [Docker] (https://docs.docker.com/), etc.
|
||||
|
||||
First, make sure your development machine has
|
||||
[VirtualBox](http://www.virtualbox.org)
|
||||
[VirtualBox](https://www.virtualbox.org/)
|
||||
installed. After this,
|
||||
[download and install the appropriate Vagrant package for your OS](http://www.vagrantup.com/downloads).
|
||||
|
||||
|
@ -55,7 +55,7 @@ Ruby 2.0 is needed.
|
|||
|
||||
### Dependencies and Unit Tests
|
||||
|
||||
To hack on Vagrant, you'll need [bundler](http://github.com/carlhuda/bundler) which can
|
||||
To hack on Vagrant, you'll need [bundler](https://github.com/bundler/bundler) which can
|
||||
be installed with a simple `gem install bundler`. Afterwards, do the following:
|
||||
|
||||
bundle install
|
||||
|
|
|
@ -10,5 +10,7 @@ for each item will be kept below.
|
|||
* `emacs` - Contains a file for enabling Ruby syntax highlighting for `Vagrantfile`s in `emacs`.
|
||||
* `st` - Contains a `.sublime-settings` file for enabling Ruby syntax highlighting
|
||||
for `Vagrantfile`s in Sublime Text.
|
||||
* `sudoers` - Contains the pieces of `/etc/sudoers` configuration to avoid password entry when
|
||||
starting machines.
|
||||
* `vim` - Contains a `.vim` file for enabling Ruby syntax highlighting
|
||||
for `Vagrantfile`s in `vim`.
|
||||
for `Vagrantfile`s in `vim`.
|
||||
|
|
|
@ -2,5 +2,6 @@ Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports
|
|||
Cmnd_Alias VAGRANT_NFSD_CHECK = /usr/bin/systemctl status nfs-server.service
|
||||
Cmnd_Alias VAGRANT_NFSD_START = /usr/bin/systemctl start nfs-server.service
|
||||
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports
|
||||
%vagrant ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /*/exports
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE_2 = /bin/cp /*/exports /etc/exports
|
||||
%vagrant ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE, VAGRANT_EXPORTS_REMOVE_2
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports
|
||||
Cmnd_Alias VAGRANT_NFSD_CHECK = /sbin/service nfsserver status
|
||||
Cmnd_Alias VAGRANT_NFSD_START = /sbin/service nfsserver start
|
||||
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -r -e * d -ibak /*/exports
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE_2 = /usr/bin/cp /*/exports /etc/exports
|
||||
%vagrant ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE, VAGRANT_EXPORTS_REMOVE_2
|
|
@ -4,5 +4,6 @@ Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports
|
|||
Cmnd_Alias VAGRANT_NFSD_CHECK = /etc/init.d/nfs-kernel-server status
|
||||
Cmnd_Alias VAGRANT_NFSD_START = /etc/init.d/nfs-kernel-server start
|
||||
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports
|
||||
%sudo ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /*/exports
|
||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE_2 = /bin/cp /*/exports /etc/exports
|
||||
%sudo ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE, VAGRANT_EXPORTS_REMOVE_2
|
||||
|
|
|
@ -381,7 +381,9 @@ module Vagrant
|
|||
@logger.info("URL is a file or protocol not found and assuming file.")
|
||||
file_path = File.expand_path(url)
|
||||
file_path = Util::Platform.cygwin_windows_path(file_path)
|
||||
url = "file:#{file_path}"
|
||||
file_path = file_path.gsub("\\", "/")
|
||||
file_path = "/#{file_path}" if !file_path.start_with?("/")
|
||||
url = "file://#{file_path}"
|
||||
end
|
||||
|
||||
# If the temporary path exists, verify it is not too old. If its
|
||||
|
@ -491,6 +493,12 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
# If this isn't HTTP, then don't do the HEAD request
|
||||
if !uri.scheme.downcase.start_with?("http")
|
||||
@logger.info("not checking metadata since box URI isn't HTTP")
|
||||
return false
|
||||
end
|
||||
|
||||
output = d.head
|
||||
match = output.scan(/^Content-Type: (.+?)$/i).last
|
||||
return false if !match
|
||||
|
@ -507,14 +515,14 @@ module Vagrant
|
|||
Digest::SHA2
|
||||
else
|
||||
raise Errors::BoxChecksumInvalidType,
|
||||
type: env[:box_checksum_type].to_s
|
||||
type: checksum_type.to_s
|
||||
end
|
||||
|
||||
@logger.info("Validating checksum with #{checksum_klass}")
|
||||
@logger.info("Expected checksum: #{checksum}")
|
||||
|
||||
actual = FileChecksum.new(path, checksum_klass).checksum
|
||||
if actual != checksum
|
||||
if actual.casecmp(checksum) != 0
|
||||
raise Errors::BoxChecksumMismatch,
|
||||
actual: actual,
|
||||
expected: checksum
|
||||
|
|
|
@ -37,13 +37,23 @@ module Vagrant
|
|||
end
|
||||
|
||||
constraints = machine.config.vm.box_version
|
||||
# Have download options specified in the environment override
|
||||
# options specified for the machine.
|
||||
download_options = {
|
||||
ca_cert: env[:ca_cert] || machine.config.vm.box_download_ca_cert,
|
||||
ca_path: env[:ca_path] || machine.config.vm.box_download_ca_path,
|
||||
client_cert: env[:client_cert] ||
|
||||
machine.config.vm.box_download_client_cert,
|
||||
insecure: !env[:insecure].nil? ?
|
||||
env[:insecure] : machine.config.vm.box_download_insecure
|
||||
}
|
||||
|
||||
env[:ui].output(I18n.t(
|
||||
"vagrant.box_outdated_checking_with_refresh",
|
||||
name: box.name))
|
||||
update = nil
|
||||
begin
|
||||
update = box.has_update?(constraints)
|
||||
update = box.has_update?(constraints, download_options: download_options)
|
||||
rescue Errors::BoxMetadataDownloadError => e
|
||||
env[:ui].warn(I18n.t(
|
||||
"vagrant.box_outdated_metadata_download_error",
|
||||
|
|
|
@ -111,6 +111,7 @@ module Vagrant
|
|||
provider: box.provider,
|
||||
version: box.version))
|
||||
box.destroy!
|
||||
env[:box_collection].clean(box.name)
|
||||
|
||||
# Passes on the removed box to the rest of the middleware chain
|
||||
env[:box_removed] = box
|
||||
|
|
|
@ -128,7 +128,7 @@ module Vagrant
|
|||
port_checker[repaired_port] ||
|
||||
lease_check(repaired_port)
|
||||
if in_use
|
||||
@logger.info("Reparied port also in use: #{repaired_port}. Trying another...")
|
||||
@logger.info("Repaired port also in use: #{repaired_port}. Trying another...")
|
||||
next
|
||||
end
|
||||
|
||||
|
@ -156,8 +156,6 @@ module Vagrant
|
|||
new_port: repaired_port.to_s))
|
||||
end
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
def lease_check(port)
|
||||
|
|
|
@ -76,6 +76,16 @@ module Vagrant
|
|||
if opts[:merge]
|
||||
existing = cached_synced_folders(machine)
|
||||
if existing
|
||||
if opts[:vagrantfile]
|
||||
# Go through and find any cached that were from the
|
||||
# Vagrantfile itself. We remove those if it was requested.
|
||||
existing.each do |impl, fs|
|
||||
fs.each do |id, data|
|
||||
fs.delete(id) if data[:__vagrantfile]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
folders.each do |impl, fs|
|
||||
existing[impl] ||= {}
|
||||
fs.each do |id, data|
|
||||
|
@ -101,7 +111,12 @@ module Vagrant
|
|||
return cached_synced_folders(machine) if opts[:cached]
|
||||
|
||||
config = opts[:config]
|
||||
config ||= machine.config.vm
|
||||
root = false
|
||||
if !config
|
||||
config = machine.config.vm
|
||||
root = true
|
||||
end
|
||||
|
||||
config_folders = config.synced_folders
|
||||
folders = {}
|
||||
|
||||
|
@ -131,9 +146,17 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
# Get the data to store
|
||||
data = data.dup
|
||||
if root
|
||||
# If these are the root synced folders (attached directly)
|
||||
# to the Vagrantfile, then we mark it as such.
|
||||
data[:__vagrantfile] = true
|
||||
end
|
||||
|
||||
# Keep track of this shared folder by the implementation.
|
||||
folders[impl] ||= {}
|
||||
folders[impl][id] = data.dup
|
||||
folders[impl][id] = data
|
||||
end
|
||||
|
||||
# If we have folders with the "default" key, then determine the
|
||||
|
|
|
@ -13,8 +13,9 @@ module Vagrant
|
|||
def initialize(app, env, place=nil)
|
||||
@app = app
|
||||
@logger = Log4r::Logger.new("vagrant::action::builtin::provision_cleanup")
|
||||
@place ||= :after
|
||||
@place = @place.to_sym
|
||||
|
||||
place ||= :after
|
||||
@place = place.to_sym
|
||||
end
|
||||
|
||||
def call(env)
|
||||
|
@ -31,10 +32,20 @@ module Vagrant
|
|||
|
||||
# Ask the provisioners to modify the configuration if needed
|
||||
provisioner_instances(env).each do |p, _|
|
||||
env[:ui].info(I18n.t(
|
||||
"vagrant.provisioner_cleanup",
|
||||
name: type_map[p].to_s))
|
||||
p.cleanup
|
||||
name = type_map[p].to_s
|
||||
|
||||
# Check if the subclass defined a cleanup method. The parent
|
||||
# provisioning class defines a `cleanup` method, so we cannot use
|
||||
# `respond_to?` here. Instead, we have to check if _this_ instance
|
||||
# defines a cleanup task.
|
||||
if p.public_methods(false).include?(:cleanup)
|
||||
env[:ui].info(I18n.t("vagrant.provisioner_cleanup",
|
||||
name: name,
|
||||
))
|
||||
p.cleanup
|
||||
else
|
||||
@logger.debug("Skipping cleanup tasks for `#{name}' - not defined")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,6 +23,7 @@ module Vagrant
|
|||
config: env[:synced_folders_config],
|
||||
}
|
||||
|
||||
@logger.info("SyncedFolders loading from cache: #{opts[:cached]}")
|
||||
folders = synced_folders(env[:machine], **opts)
|
||||
original_folders = folders
|
||||
|
||||
|
@ -121,8 +122,11 @@ module Vagrant
|
|||
|
||||
save_synced_folders(env[:machine], all)
|
||||
else
|
||||
save_opts = { merge: true }
|
||||
save_opts[:vagrantfile] = true if !opts[:config]
|
||||
|
||||
# Save the synced folders
|
||||
save_synced_folders(env[:machine], original_folders, merge: true)
|
||||
save_synced_folders(env[:machine], original_folders, **save_opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,7 +30,7 @@ module Vagrant
|
|||
def call(env)
|
||||
@env = env
|
||||
file_name = File.basename(@env["package.output"].to_s)
|
||||
|
||||
|
||||
raise Errors::PackageOutputDirectory if File.directory?(tar_path)
|
||||
raise Errors::PackageOutputExists, file_name:file_name if File.exist?(tar_path)
|
||||
raise Errors::PackageRequiresDirectory if !env["package.directory"] ||
|
||||
|
@ -113,6 +113,21 @@ module Vagrant
|
|||
|
||||
# If we don't have a generated private key, we do nothing
|
||||
path = @env[:machine].data_dir.join("private_key")
|
||||
if !path.file?
|
||||
# If we have a private key that was copied into this box,
|
||||
# then we copy that. This is a bit of a heuristic and can be a
|
||||
# security risk if the key is named the correct thing, but
|
||||
# we'll take that risk for dev environments.
|
||||
(@env[:machine].config.ssh.private_key_path || []).each do |p|
|
||||
# If we have the correctly named key, copy it
|
||||
if File.basename(p) == "vagrant_private_key"
|
||||
path = Pathname.new(p)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# If we still have no matching key, do nothing
|
||||
return if !path.file?
|
||||
|
||||
# Copy it into our box directory
|
||||
|
|
|
@ -115,8 +115,9 @@ module Vagrant
|
|||
# Loads the metadata URL and returns the latest metadata associated
|
||||
# with this box.
|
||||
#
|
||||
# @param [Hash] download_options Options to pass to the downloader.
|
||||
# @return [BoxMetadata]
|
||||
def load_metadata
|
||||
def load_metadata(**download_options)
|
||||
tf = Tempfile.new("vagrant")
|
||||
tf.close
|
||||
|
||||
|
@ -127,7 +128,7 @@ module Vagrant
|
|||
url = "file:#{url}"
|
||||
end
|
||||
|
||||
opts = { headers: ["Accept: application/json"] }
|
||||
opts = { headers: ["Accept: application/json"] }.merge(download_options)
|
||||
Util::Downloader.new(url, tf.path, **opts).download!
|
||||
BoxMetadata.new(File.open(tf.path, "r"))
|
||||
rescue Errors::DownloaderError => e
|
||||
|
@ -148,7 +149,7 @@ module Vagrant
|
|||
# satisfy. If nil, the version constrain defaults to being a
|
||||
# larger version than this box.
|
||||
# @return [Array]
|
||||
def has_update?(version=nil)
|
||||
def has_update?(version=nil, download_options: {})
|
||||
if !@metadata_url
|
||||
raise Errors::BoxUpdateNoMetadata, name: @name
|
||||
end
|
||||
|
@ -156,7 +157,7 @@ module Vagrant
|
|||
version += ", " if version
|
||||
version ||= ""
|
||||
version += "> #{@version}"
|
||||
md = self.load_metadata
|
||||
md = self.load_metadata(download_options)
|
||||
newer = md.version(version, provider: @provider)
|
||||
return nil if !newer
|
||||
|
||||
|
|
|
@ -12,7 +12,9 @@ module Vagrant
|
|||
# for accessing/finding individual boxes, adding new boxes, or deleting
|
||||
# boxes.
|
||||
class BoxCollection
|
||||
TEMP_PREFIX = "vagrant-box-add-temp-"
|
||||
TEMP_PREFIX = "vagrant-box-add-temp-".freeze
|
||||
VAGRANT_SLASH = "-VAGRANTSLASH-".freeze
|
||||
VAGRANT_COLON = "-VAGRANTCOLON-".freeze
|
||||
|
||||
# The directory where the boxes in this collection are stored.
|
||||
#
|
||||
|
@ -346,6 +348,14 @@ module Vagrant
|
|||
end
|
||||
end
|
||||
|
||||
# Cleans the directory for a box by removing the folders that are
|
||||
# empty.
|
||||
def clean(name)
|
||||
return false if exists?(name)
|
||||
path = File.join(directory, dir_name(name))
|
||||
FileUtils.rm_rf(path)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Returns the directory name for the box of the given name.
|
||||
|
@ -354,16 +364,16 @@ module Vagrant
|
|||
# @return [String]
|
||||
def dir_name(name)
|
||||
name = name.dup
|
||||
name.gsub!(":", "-VAGRANTCOLON-") if Util::Platform.windows?
|
||||
name.gsub!("/", "-VAGRANTSLASH-")
|
||||
name.gsub!(":", VAGRANT_COLON) if Util::Platform.windows?
|
||||
name.gsub!("/", VAGRANT_SLASH)
|
||||
name
|
||||
end
|
||||
|
||||
# Returns the directory name for the box cleaned up
|
||||
def undir_name(name)
|
||||
name = name.dup
|
||||
name.gsub!("-VAGRANTCOLON-", ":")
|
||||
name.gsub!("-VAGRANTSLASH-", "/")
|
||||
name.gsub!(VAGRANT_COLON, ":")
|
||||
name.gsub!(VAGRANT_SLASH, "/")
|
||||
name
|
||||
end
|
||||
|
||||
|
@ -440,5 +450,10 @@ module Vagrant
|
|||
ensure
|
||||
dir.rmtree if dir.exist?
|
||||
end
|
||||
|
||||
# Checks if a box with a given name exists.
|
||||
def exists?(box_name)
|
||||
all.any? { |box| box.first.eql?(box_name) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ require "bundler"
|
|||
|
||||
require_relative "shared_helpers"
|
||||
require_relative "version"
|
||||
require_relative "util/safe_env"
|
||||
|
||||
module Vagrant
|
||||
# This class manages Vagrant's interaction with Bundler. Vagrant uses
|
||||
|
@ -42,6 +43,9 @@ module Vagrant
|
|||
yield
|
||||
end
|
||||
end
|
||||
|
||||
# Configure Bundler to retry
|
||||
::Bundler.settings[:retry] = 3
|
||||
end
|
||||
|
||||
# Initializes Bundler and the various gem paths so that we can begin
|
||||
|
@ -68,12 +72,15 @@ module Vagrant
|
|||
# we add all our plugin dependencies.
|
||||
@gemfile = build_gemfile(plugins)
|
||||
|
||||
# Set the environmental variables for Bundler
|
||||
ENV["BUNDLE_APP_CONFIG"] = @appconfigpath
|
||||
ENV["BUNDLE_CONFIG"] = @configfile.path
|
||||
ENV["BUNDLE_GEMFILE"] = @gemfile.path
|
||||
ENV["GEM_PATH"] =
|
||||
"#{bundle_path}#{::File::PATH_SEPARATOR}#{@gem_path}"
|
||||
Util::SafeEnv.change_env do |env|
|
||||
# Set the environmental variables for Bundler
|
||||
env["BUNDLE_APP_CONFIG"] = @appconfigpath
|
||||
env["BUNDLE_CONFIG"] = @configfile.path
|
||||
env["BUNDLE_GEMFILE"] = @gemfile.path
|
||||
env["GEM_PATH"] =
|
||||
"#{bundle_path}#{::File::PATH_SEPARATOR}#{@gem_path}"
|
||||
end
|
||||
|
||||
Gem.clear_paths
|
||||
end
|
||||
|
||||
|
@ -178,11 +185,6 @@ module Vagrant
|
|||
|
||||
f = File.open(Tempfile.new("vagrant").path + "2", "w+")
|
||||
f.tap do |gemfile|
|
||||
if !sources.include?("http://rubygems.org")
|
||||
gemfile.puts(%Q[source "https://rubygems.org"])
|
||||
end
|
||||
|
||||
gemfile.puts(%Q[source "http://gems.hashicorp.com"])
|
||||
sources.each do |source|
|
||||
next if source == ""
|
||||
gemfile.puts(%Q[source "#{source}"])
|
||||
|
|
|
@ -221,7 +221,12 @@ module Vagrant
|
|||
|
||||
line = "(unknown)"
|
||||
if e.backtrace && e.backtrace[0]
|
||||
line = e.backtrace[0].split(":")[1]
|
||||
e.backtrace[0].split(":").each do |part|
|
||||
if part =~ /\d+/
|
||||
line = part.to_i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Report the generic exception
|
||||
|
|
|
@ -832,7 +832,7 @@ module Vagrant
|
|||
|
||||
# This creates the local data directory and show an error if it
|
||||
# couldn't properly be created.
|
||||
def setup_local_data_path
|
||||
def setup_local_data_path(force=false)
|
||||
if @local_data_path.nil?
|
||||
@logger.warn("No local data path is set. Local data cannot be stored.")
|
||||
return
|
||||
|
@ -847,6 +847,9 @@ module Vagrant
|
|||
upgrade_v1_dotfile(@local_data_path)
|
||||
end
|
||||
|
||||
# If we don't have a root path, we don't setup anything
|
||||
return if !force && root_path.nil?
|
||||
|
||||
begin
|
||||
@logger.debug("Creating: #{@local_data_path}")
|
||||
FileUtils.mkdir_p(@local_data_path)
|
||||
|
@ -965,7 +968,7 @@ module Vagrant
|
|||
|
||||
# Now, we create the actual local data directory. This should succeed
|
||||
# this time since we renamed the old conflicting V1.
|
||||
setup_local_data_path
|
||||
setup_local_data_path(true)
|
||||
|
||||
if json_data["active"]
|
||||
@logger.debug("Upgrading to V2 style for each active VM")
|
||||
|
|
|
@ -108,14 +108,6 @@ module Vagrant
|
|||
error_key(:active_machine_with_different_provider)
|
||||
end
|
||||
|
||||
class AnsibleFailed < VagrantError
|
||||
error_key(:ansible_failed)
|
||||
end
|
||||
|
||||
class AnsiblePlaybookAppNotFound < VagrantError
|
||||
error_key(:ansible_playbook_app_not_found)
|
||||
end
|
||||
|
||||
class BatchMultiError < VagrantError
|
||||
error_key(:batch_multi_error)
|
||||
end
|
||||
|
@ -248,6 +240,10 @@ module Vagrant
|
|||
error_key(:bundler_error)
|
||||
end
|
||||
|
||||
class CantReadMACAddresses < VagrantError
|
||||
error_key(:cant_read_mac_addresses)
|
||||
end
|
||||
|
||||
class CapabilityHostExplicitNotDetected < VagrantError
|
||||
error_key(:capability_host_explicit_not_detected)
|
||||
end
|
||||
|
@ -348,6 +344,10 @@ module Vagrant
|
|||
error_key(:downloader_interrupted)
|
||||
end
|
||||
|
||||
class EnvInval < VagrantError
|
||||
error_key(:env_inval)
|
||||
end
|
||||
|
||||
class EnvironmentNonExistentCWD < VagrantError
|
||||
error_key(:environment_non_existent_cwd)
|
||||
end
|
||||
|
@ -408,8 +408,8 @@ module Vagrant
|
|||
error_key(:linux_nfs_mount_failed)
|
||||
end
|
||||
|
||||
class LinuxRDesktopNotFound < VagrantError
|
||||
error_key(:linux_rdesktop_not_found)
|
||||
class LinuxRDPClientNotFound < VagrantError
|
||||
error_key(:linux_rdp_client_not_found)
|
||||
end
|
||||
|
||||
class LocalDataDirectoryNotAccessible < VagrantError
|
||||
|
@ -524,6 +524,10 @@ module Vagrant
|
|||
error_key(:provider_cant_install)
|
||||
end
|
||||
|
||||
class ProviderChecksumMismatch < VagrantError
|
||||
error_key(:provider_checksum_mismatch)
|
||||
end
|
||||
|
||||
class ProviderInstallFailed < VagrantError
|
||||
error_key(:provider_install_failed)
|
||||
end
|
||||
|
|
|
@ -116,6 +116,9 @@ module Vagrant
|
|||
# XXX: This is temporary. This will be removed very soon.
|
||||
if base
|
||||
@id = name
|
||||
|
||||
# For base setups, we don't want to insert the key
|
||||
@config.ssh.insert_key = false
|
||||
else
|
||||
reload
|
||||
end
|
||||
|
@ -141,6 +144,10 @@ module Vagrant
|
|||
if state.id == MachineState::NOT_CREATED_ID
|
||||
self.id = nil
|
||||
end
|
||||
|
||||
# Output a bunch of information about this machine in
|
||||
# machine-readable format in case someone is listening.
|
||||
@ui.machine("metadata", "provider", provider_name)
|
||||
end
|
||||
|
||||
# This calls an action on the provider. The provider may or may not
|
||||
|
@ -188,7 +195,10 @@ module Vagrant
|
|||
end
|
||||
|
||||
# Call the action
|
||||
action_raw(name, callable, extra_env)
|
||||
ui.machine("action", name.to_s, "start")
|
||||
action_result = action_raw(name, callable, extra_env)
|
||||
ui.machine("action", name.to_s, "end")
|
||||
action_result
|
||||
end
|
||||
rescue Errors::EnvironmentLockedError
|
||||
raise Errors::MachineActionLockedError,
|
||||
|
@ -436,6 +446,7 @@ module Vagrant
|
|||
# We also set some fields that are purely controlled by Varant
|
||||
info[:forward_agent] = @config.ssh.forward_agent
|
||||
info[:forward_x11] = @config.ssh.forward_x11
|
||||
info[:forward_env] = @config.ssh.forward_env
|
||||
|
||||
info[:ssh_command] = @config.ssh.ssh_command if @config.ssh.ssh_command
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ module Vagrant
|
|||
@machines.delete(entry.id)
|
||||
unlocked_save
|
||||
|
||||
# Release acccess on this machine
|
||||
# Release access on this machine
|
||||
unlocked_release(entry.id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -133,8 +133,17 @@ module Vagrant
|
|||
# machine in that environment. We silence warnings here because
|
||||
# Vagrantfiles often have constants, so people would otherwise
|
||||
# constantly (heh) get "already initialized constant" warnings.
|
||||
env = entry.vagrant_env(
|
||||
@env.home_path, ui_class: @env.ui_class)
|
||||
begin
|
||||
env = entry.vagrant_env(
|
||||
@env.home_path, ui_class: @env.ui_class)
|
||||
rescue Vagrant::Errors::EnvironmentNonExistentCWD
|
||||
# This means that this environment working directory
|
||||
# no longer exists, so delete this entry.
|
||||
entry = @env.machine_index.get(name.to_s)
|
||||
@env.machine_index.delete(entry) if entry
|
||||
raise
|
||||
end
|
||||
|
||||
next env.machine(entry.name.to_sym, entry.provider.to_sym)
|
||||
end
|
||||
|
||||
|
|
|
@ -104,8 +104,8 @@ module Vagrant
|
|||
end
|
||||
|
||||
[:detail, :warn, :error, :info, :output, :success].each do |method|
|
||||
define_method(method) do |message, *opts|
|
||||
machine("ui", method.to_s, message)
|
||||
define_method(method) do |message, *args, **opts|
|
||||
machine("ui", method.to_s, message, *args, **opts)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -123,9 +123,12 @@ module Vagrant
|
|||
data[i].gsub!("\r", "\\r")
|
||||
end
|
||||
|
||||
@lock.synchronize do
|
||||
safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
|
||||
end
|
||||
# Avoid locks in a trap context introduced from Ruby 2.0
|
||||
Thread.new do
|
||||
@lock.synchronize do
|
||||
safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
|
||||
end
|
||||
end.join
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -156,7 +159,7 @@ module Vagrant
|
|||
super(message)
|
||||
|
||||
# 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.windows?
|
||||
|
||||
# Setup the options so that the new line is suppressed
|
||||
opts ||= {}
|
||||
|
@ -277,6 +280,9 @@ module Vagrant
|
|||
opts[:bold] = #{method.inspect} != :detail && \
|
||||
#{method.inspect} != :ask
|
||||
end
|
||||
if !opts.key?(:target)
|
||||
opts[:target] = @prefix
|
||||
end
|
||||
@ui.#{method}(format_message(#{method.inspect}, message, **opts), *args, **opts)
|
||||
end
|
||||
CODE
|
||||
|
|
|
@ -138,11 +138,14 @@ module Vagrant
|
|||
# If we already retried, raise it.
|
||||
raise if retried
|
||||
|
||||
@logger.error("Exit code: #{e.extra_data[:code]}")
|
||||
|
||||
# If its any error other than 33, it is an error.
|
||||
raise if e.extra_data[:exit_code].to_i != 33
|
||||
raise if e.extra_data[:code].to_i != 33
|
||||
|
||||
# Exit code 33 means that the server doesn't support ranges.
|
||||
# In this case, try again without resume.
|
||||
@logger.error("Error is server doesn't support byte ranges. Retrying from scratch.")
|
||||
@continue = false
|
||||
retried = true
|
||||
retry
|
||||
|
|
|
@ -10,10 +10,17 @@ module Vagrant
|
|||
class Platform
|
||||
class << self
|
||||
def cygwin?
|
||||
# Installer detects Cygwin
|
||||
return true if ENV["VAGRANT_DETECTED_OS"] &&
|
||||
ENV["VAGRANT_DETECTED_OS"].downcase.include?("cygwin")
|
||||
|
||||
platform.include?("cygwin")
|
||||
# Ruby running in Cygwin
|
||||
return true if platform.include?("cygwin")
|
||||
|
||||
# Heuristic. If the path contains Cygwin, we just assume we're
|
||||
# in Cygwin. It is generally a safe bet.
|
||||
path = ENV["PATH"] || ""
|
||||
return path.include?("cygwin")
|
||||
end
|
||||
|
||||
[:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
|
||||
|
@ -45,10 +52,32 @@ module Vagrant
|
|||
# detect-if-running-with-administrator-privileges-under-windows-xp
|
||||
begin
|
||||
Win32::Registry::HKEY_USERS.open("S-1-5-19") {}
|
||||
return true
|
||||
rescue Win32::Registry::Error
|
||||
return false
|
||||
end
|
||||
|
||||
# If we made it this far then we try a fallback approach
|
||||
# since the above doesn't seem to be bullet proof. See GH-5616
|
||||
(`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil?
|
||||
end
|
||||
|
||||
# Checks if the user running Vagrant on Windows is a member of the
|
||||
# "Hyper-V Administrators" group.
|
||||
#
|
||||
# From: https://support.microsoft.com/en-us/kb/243330
|
||||
# SID: S-1-5-32-578
|
||||
# Name: BUILTIN\Hyper-V Administrators
|
||||
#
|
||||
# @return [Boolean]
|
||||
def windows_hyperv_admin?
|
||||
begin
|
||||
username = ENV["USERNAME"]
|
||||
process = Subprocess.execute("net", "localgroup", "Hyper-V Administrators")
|
||||
output = process.stdout.chomp
|
||||
return output.include?(username)
|
||||
rescue Errors::CommandUnavailableWindows
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
# This takes any path and converts it from a Windows path to a
|
||||
|
@ -114,6 +143,14 @@ module Vagrant
|
|||
path = Pathname.new(File.expand_path(path))
|
||||
|
||||
if path.exist? && !fs_case_sensitive?
|
||||
# If the path contains a Windows short path, then we attempt to
|
||||
# expand. The require below is embedded here since it requires
|
||||
# windows to work.
|
||||
if windows? && path.to_s =~ /~\d(\/|\\)/
|
||||
require_relative "windows_path"
|
||||
path = Pathname.new(WindowsPath.longname(path.to_s))
|
||||
end
|
||||
|
||||
# Build up all the parts of the path
|
||||
original = []
|
||||
while !path.root?
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
module Vagrant
|
||||
module Util
|
||||
module Presence
|
||||
extend self
|
||||
|
||||
# Determines if the given object is "present". A String is considered
|
||||
# present if the stripped contents are not empty. An Array/Hash is
|
||||
# considered present if they have a length of more than 1. "true" is
|
||||
# always present and `false` and `nil` are always not present. Any other
|
||||
# object is considered to be present.
|
||||
#
|
||||
# @return [true, false]
|
||||
def present?(obj)
|
||||
case obj
|
||||
when String
|
||||
!obj.strip.empty?
|
||||
when Symbol
|
||||
!obj.to_s.strip.empty?
|
||||
when Array
|
||||
!obj.compact.empty?
|
||||
when Hash
|
||||
!obj.empty?
|
||||
when TrueClass, FalseClass
|
||||
obj
|
||||
when NilClass
|
||||
false
|
||||
when Object
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
# Returns the presence of the object. If the object is {present?}, it is
|
||||
# returned. Otherwise `false` is returned.
|
||||
#
|
||||
# @return [Object, false]
|
||||
def presence(obj)
|
||||
if present?(obj)
|
||||
obj
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
module Vagrant
|
||||
module Util
|
||||
class SafeEnv
|
||||
# This yields an environment hash to change and catches any issues
|
||||
# while changing the environment variables and raises a helpful error
|
||||
# to end users.
|
||||
def self.change_env
|
||||
yield ENV
|
||||
rescue Errno::EINVAL
|
||||
raise Errors::EnvInval
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -138,6 +138,10 @@ module Vagrant
|
|||
command_options += ["-o", "ProxyCommand=#{ssh_info[:proxy_command]}"]
|
||||
end
|
||||
|
||||
if ssh_info[:forward_env]
|
||||
command_options += ["-o", "SendEnv=#{ssh_info[:forward_env].join(" ")}"]
|
||||
end
|
||||
|
||||
# Configurables -- extra_args should always be last due to the way the
|
||||
# ssh args parser works. e.g. if the user wants to use the -t option,
|
||||
# any shell command(s) she'd like to run on the remote server would
|
||||
|
@ -172,6 +176,14 @@ module Vagrant
|
|||
LOGGER.info("Executing SSH in subprocess: #{ssh} #{command_options.inspect}")
|
||||
process = ChildProcess.build(ssh, *command_options)
|
||||
process.io.inherit!
|
||||
|
||||
# Forward configured environment variables.
|
||||
if ssh_info[:forward_env]
|
||||
ssh_info[:forward_env].each do |key|
|
||||
process.environment[key] = ENV[key]
|
||||
end
|
||||
end
|
||||
|
||||
process.start
|
||||
process.wait
|
||||
return process.exit_code
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
require "fiddle/import"
|
||||
|
||||
module Vagrant
|
||||
module Util
|
||||
module WindowsPath
|
||||
module API
|
||||
extend Fiddle::Importer
|
||||
dlload 'kernel32.dll'
|
||||
extern("int GetLongPathNameA(char*, char*, int)", :stdcall)
|
||||
end
|
||||
|
||||
# Converts a Windows shortname to a long name. This only works
|
||||
# for ASCII paths currently and doesn't use the wide character
|
||||
# support.
|
||||
def self.longname(name)
|
||||
# We loop over the API call in case we didn't allocate enough
|
||||
# buffer space. In general it is usually enough.
|
||||
bufferlen = 250
|
||||
buffer = nil
|
||||
while true
|
||||
buffer = ' ' * bufferlen
|
||||
len = API.GetLongPathNameA(name.to_s, buffer, buffer.size)
|
||||
if bufferlen < len
|
||||
# If the length returned is larger than our buffer length,
|
||||
# it is the API telling us it needs more space. Allocate it
|
||||
# and retry.
|
||||
bufferlen = len
|
||||
continue
|
||||
end
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
return buffer.rstrip.chomp("\0")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,9 +1,13 @@
|
|||
require 'optparse'
|
||||
|
||||
require_relative 'download_mixins'
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandBox
|
||||
module Command
|
||||
class Add < Vagrant.plugin("2", :command)
|
||||
include DownloadMixins
|
||||
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
|
@ -21,22 +25,7 @@ module VagrantPlugins
|
|||
options[:force] = f
|
||||
end
|
||||
|
||||
o.on("--insecure", "Do not validate SSL certificates") do |i|
|
||||
options[:insecure] = i
|
||||
end
|
||||
|
||||
o.on("--cacert FILE", String, "CA certificate for SSL download") do |c|
|
||||
options[:ca_cert] = c
|
||||
end
|
||||
|
||||
o.on("--capath DIR", String, "CA certificate directory for SSL download") do |c|
|
||||
options[:ca_path] = c
|
||||
end
|
||||
|
||||
o.on("--cert FILE", String,
|
||||
"A client SSL cert, if needed") do |c|
|
||||
options[:client_cert] = c
|
||||
end
|
||||
build_download_options(o, options)
|
||||
|
||||
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
|
||||
|
@ -97,7 +86,7 @@ module VagrantPlugins
|
|||
box_force: options[:force],
|
||||
box_download_ca_cert: options[:ca_cert],
|
||||
box_download_ca_path: options[:ca_path],
|
||||
box_download_client_cert: options[:client_cert],
|
||||
box_client_cert: options[:client_cert],
|
||||
box_download_insecure: options[:insecure],
|
||||
box_download_location_trusted: options[:location_trusted],
|
||||
ui: Vagrant::UI::Prefixed.new(@env.ui, "box"),
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
module VagrantPlugins
|
||||
module CommandBox
|
||||
module DownloadMixins
|
||||
# This adds common download command line flags to the given
|
||||
# OptionParser, storing the result in the `options` dictionary.
|
||||
#
|
||||
# @param [OptionParser] parser
|
||||
# @param [Hash] options
|
||||
def build_download_options(parser, options)
|
||||
# Add the options
|
||||
parser.on("--insecure", "Do not validate SSL certificates") do |i|
|
||||
options[:insecure] = i
|
||||
end
|
||||
|
||||
parser.on("--cacert FILE", String, "CA certificate for SSL download") do |c|
|
||||
options[:ca_cert] = c
|
||||
end
|
||||
|
||||
parser.on("--capath DIR", String, "CA certificate directory for SSL download") do |c|
|
||||
options[:ca_path] = c
|
||||
end
|
||||
|
||||
parser.on("--cert FILE", String, "A client SSL cert, if needed") do |c|
|
||||
options[:client_cert] = c
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +1,16 @@
|
|||
require 'optparse'
|
||||
|
||||
require_relative 'download_mixins'
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandBox
|
||||
module Command
|
||||
class Outdated < Vagrant.plugin("2", :command)
|
||||
include DownloadMixins
|
||||
|
||||
def execute
|
||||
options = {}
|
||||
download_options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant box outdated [options]"
|
||||
|
@ -20,6 +25,8 @@ module VagrantPlugins
|
|||
o.on("--global", "Check all boxes installed") do |g|
|
||||
options[:global] = g
|
||||
end
|
||||
|
||||
build_download_options(o, download_options)
|
||||
end
|
||||
|
||||
argv = parse_options(opts)
|
||||
|
@ -27,7 +34,7 @@ module VagrantPlugins
|
|||
|
||||
# If we're checking the boxes globally, then do that.
|
||||
if options[:global]
|
||||
outdated_global
|
||||
outdated_global(download_options)
|
||||
return 0
|
||||
end
|
||||
|
||||
|
@ -37,11 +44,11 @@ module VagrantPlugins
|
|||
box_outdated_refresh: true,
|
||||
box_outdated_success_ui: true,
|
||||
machine: machine,
|
||||
})
|
||||
}.merge(download_options))
|
||||
end
|
||||
end
|
||||
|
||||
def outdated_global
|
||||
def outdated_global(download_options)
|
||||
boxes = {}
|
||||
@env.boxes.all.reverse.each do |name, version, provider|
|
||||
next if boxes[name]
|
||||
|
@ -58,8 +65,8 @@ module VagrantPlugins
|
|||
|
||||
md = nil
|
||||
begin
|
||||
md = box.load_metadata
|
||||
rescue Vagrant::Errors::DownloaderError => e
|
||||
md = box.load_metadata(download_options)
|
||||
rescue Vagrant::Errors::BoxMetadataDownloadError => e
|
||||
@env.ui.error(I18n.t(
|
||||
"vagrant.box_outdated_metadata_error",
|
||||
name: box.name,
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
require 'optparse'
|
||||
|
||||
require_relative 'download_mixins'
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandBox
|
||||
module Command
|
||||
class Update < Vagrant.plugin("2", :command)
|
||||
include DownloadMixins
|
||||
|
||||
def execute
|
||||
options = {}
|
||||
download_options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant box update [options]"
|
||||
|
@ -27,21 +32,23 @@ module VagrantPlugins
|
|||
o.on("--provider PROVIDER", String, "Update box with specific provider") do |p|
|
||||
options[:provider] = p.to_sym
|
||||
end
|
||||
|
||||
build_download_options(o, download_options)
|
||||
end
|
||||
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
if options[:box]
|
||||
update_specific(options[:box], options[:provider])
|
||||
update_specific(options[:box], options[:provider], download_options)
|
||||
else
|
||||
update_vms(argv, options[:provider])
|
||||
update_vms(argv, options[:provider], download_options)
|
||||
end
|
||||
|
||||
0
|
||||
end
|
||||
|
||||
def update_specific(name, provider)
|
||||
def update_specific(name, provider, download_options)
|
||||
boxes = {}
|
||||
@env.boxes.all.each do |n, v, p|
|
||||
boxes[n] ||= {}
|
||||
|
@ -74,11 +81,11 @@ module VagrantPlugins
|
|||
|
||||
to_update.each do |n, p, v|
|
||||
box = @env.boxes.find(n, p, v)
|
||||
box_update(box, "> #{v}", @env.ui)
|
||||
box_update(box, "> #{v}", @env.ui, download_options)
|
||||
end
|
||||
end
|
||||
|
||||
def update_vms(argv, provider)
|
||||
def update_vms(argv, provider, download_options)
|
||||
with_target_vms(argv, provider: provider) do |machine|
|
||||
if !machine.config.vm.box
|
||||
machine.ui.output(I18n.t(
|
||||
|
@ -95,17 +102,25 @@ module VagrantPlugins
|
|||
|
||||
box = machine.box
|
||||
version = machine.config.vm.box_version
|
||||
box_update(box, version, machine.ui)
|
||||
# Get download options from machine configuration if not specified
|
||||
# on the command line.
|
||||
download_options[:ca_cert] ||= machine.config.vm.box_download_ca_cert
|
||||
download_options[:ca_path] ||= machine.config.vm.box_download_ca_path
|
||||
download_options[:client_cert] ||= machine.config.vm.box_download_client_cert
|
||||
if download_options[:insecure].nil?
|
||||
download_options[:insecure] = machine.config.vm.box_download_insecure
|
||||
end
|
||||
box_update(box, version, machine.ui, download_options)
|
||||
end
|
||||
end
|
||||
|
||||
def box_update(box, version, ui)
|
||||
def box_update(box, version, ui, download_options)
|
||||
ui.output(I18n.t("vagrant.box_update_checking", name: box.name))
|
||||
ui.detail("Latest installed version: #{box.version}")
|
||||
ui.detail("Version constraints: #{version}")
|
||||
ui.detail("Provider: #{box.provider}")
|
||||
|
||||
update = box.has_update?(version)
|
||||
update = box.has_update?(version, download_options: download_options)
|
||||
if !update
|
||||
ui.success(I18n.t(
|
||||
"vagrant.box_up_to_date_single",
|
||||
|
@ -124,6 +139,10 @@ module VagrantPlugins
|
|||
box_provider: update[2].name,
|
||||
box_version: update[1].version,
|
||||
ui: ui,
|
||||
box_client_cert: download_options[:client_cert],
|
||||
box_download_ca_cert: download_options[:ca_cert],
|
||||
box_download_ca_path: download_options[:ca_path],
|
||||
box_download_insecure: download_options[:insecure]
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require "rest_client"
|
||||
require "vagrant/util/downloader"
|
||||
|
||||
module VagrantPlugins
|
||||
module LoginCommand
|
||||
|
@ -45,8 +46,23 @@ module VagrantPlugins
|
|||
with_error_handling do
|
||||
url = "#{Vagrant.server_url}/api/v1/authenticate"
|
||||
request = { "user" => { "login" => user, "password" => pass } }
|
||||
response = RestClient.post(
|
||||
url, JSON.dump(request), content_type: :json)
|
||||
|
||||
proxy = nil
|
||||
proxy ||= ENV["HTTPS_PROXY"] || ENV["https_proxy"]
|
||||
proxy ||= ENV["HTTP_PROXY"] || ENV["http_proxy"]
|
||||
|
||||
response = RestClient::Request.execute(
|
||||
method: :post,
|
||||
url: url,
|
||||
payload: JSON.dump(request),
|
||||
proxy: proxy,
|
||||
headers: {
|
||||
accept: :json,
|
||||
content_type: :json,
|
||||
user_agent: Vagrant::Util::Downloader::USER_AGENT,
|
||||
},
|
||||
)
|
||||
|
||||
data = JSON.load(response.to_s)
|
||||
data["token"]
|
||||
end
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
require "cgi"
|
||||
require "uri"
|
||||
|
||||
require_relative "../client"
|
||||
|
@ -5,6 +6,9 @@ require_relative "../client"
|
|||
module VagrantPlugins
|
||||
module LoginCommand
|
||||
class AddAuthentication
|
||||
VCLOUD = "vagrantcloud.com".freeze
|
||||
ATLAS = "atlas.hashicorp.com".freeze
|
||||
|
||||
def initialize(app, env)
|
||||
@app = app
|
||||
end
|
||||
|
@ -19,19 +23,26 @@ module VagrantPlugins
|
|||
env[:box_urls].map! do |url|
|
||||
u = URI.parse(url)
|
||||
replace = u.host == server_uri.host
|
||||
|
||||
if !replace
|
||||
# We need this in here for the transition we made from
|
||||
# Vagrant Cloud to Atlas. This preserves access tokens
|
||||
# appending to both without leaking access tokens to
|
||||
# unsavory URLs.
|
||||
replace = u.host == "vagrantcloud.com" &&
|
||||
server_uri.host == "atlas.hashicorp.com"
|
||||
if u.host == VCLOUD && server_uri.host == ATLAS
|
||||
replace = true
|
||||
end
|
||||
end
|
||||
|
||||
if replace
|
||||
u.query ||= ""
|
||||
u.query += "&" if u.query != ""
|
||||
u.query += "access_token=#{token}"
|
||||
q = CGI.parse(u.query || "")
|
||||
|
||||
current = q["access_token"]
|
||||
if current && current.empty?
|
||||
q["access_token"] = token
|
||||
end
|
||||
|
||||
u.query = URI.encode_www_form(q)
|
||||
end
|
||||
|
||||
u.to_s
|
||||
|
|
|
@ -3,6 +3,11 @@ module VagrantPlugins
|
|||
module Command
|
||||
module MixinInstallOpts
|
||||
def build_install_opts(o, options)
|
||||
options[:plugin_sources] = [
|
||||
"https://rubygems.org",
|
||||
"http://gems.hashicorp.com",
|
||||
]
|
||||
|
||||
o.on("--entry-point NAME", String,
|
||||
"The name of the entry point file for loading the plugin.") do |entry_point|
|
||||
options[:entry_point] = entry_point
|
||||
|
@ -17,9 +22,13 @@ module VagrantPlugins
|
|||
puts
|
||||
end
|
||||
|
||||
o.on("--plugin-clean-sources",
|
||||
"Remove all plugin sources defined so far (including defaults)") do |clean|
|
||||
options[:plugin_sources] = [] if clean
|
||||
end
|
||||
|
||||
o.on("--plugin-source PLUGIN_SOURCE", String,
|
||||
"Add a RubyGems repository source") do |plugin_source|
|
||||
options[:plugin_sources] ||= []
|
||||
options[:plugin_sources] << plugin_source
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
require "vagrant/util/presence"
|
||||
|
||||
require "optparse"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPort
|
||||
class Command < Vagrant.plugin("2", :command)
|
||||
include Vagrant::Util::Presence
|
||||
|
||||
def self.synopsis
|
||||
"displays information about guest port mappings"
|
||||
end
|
||||
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant port [options] [name]"
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("--guest PORT", "Output the host port that maps to the given guest port") do |port|
|
||||
options[:guest] = port
|
||||
end
|
||||
|
||||
o.on("--machine-readable", "Display machine-readable output")
|
||||
end
|
||||
|
||||
# Parse the options
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
with_target_vms(argv, single_target: true) do |vm|
|
||||
vm.action_raw(:config_validate,
|
||||
Vagrant::Action::Builtin::ConfigValidate)
|
||||
|
||||
if !vm.provider.capability?(:forwarded_ports)
|
||||
@env.ui.error(I18n.t("port_command.missing_capability",
|
||||
provider: vm.provider_name,
|
||||
))
|
||||
return 1
|
||||
end
|
||||
|
||||
ports = vm.provider.capability(:forwarded_ports)
|
||||
|
||||
if !present?(ports)
|
||||
@env.ui.info(I18n.t("port_command.empty_ports"))
|
||||
return 0
|
||||
end
|
||||
|
||||
if present?(options[:guest])
|
||||
return print_single(vm, ports, options[:guest])
|
||||
else
|
||||
return print_all(vm, ports)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Print all the guest <=> host port mappings.
|
||||
# @return [0] the exit code
|
||||
def print_all(vm, ports)
|
||||
@env.ui.info(I18n.t("port_command.details"))
|
||||
@env.ui.info("")
|
||||
ports.each do |host, guest|
|
||||
@env.ui.info("#{guest.to_s.rjust(6)} (guest) => #{host} (host)")
|
||||
@env.ui.machine("forwarded_port", guest, host, target: vm.name.to_s)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
# Print the host mapping that matches the given guest target.
|
||||
# @return [0,1] the exit code
|
||||
def print_single(vm, ports, target)
|
||||
map = ports.find { |_, guest| "#{guest}" == "#{target}" }
|
||||
if !present?(map)
|
||||
@env.ui.error(I18n.t("port_command.no_matching_port",
|
||||
port: target,
|
||||
))
|
||||
return 1
|
||||
end
|
||||
|
||||
@env.ui.info("#{map[0]}")
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
en:
|
||||
port_command:
|
||||
details: |-
|
||||
The forwarded ports for the machine are listed below. Please note that
|
||||
these values may differ from values configured in the Vagrantfile if the
|
||||
provider supports automatic port collision detection and resolution.
|
||||
empty_ports: |-
|
||||
The provider reported there are no forwarded ports for this virtual
|
||||
machine. This can be caused if there are no ports specified in the
|
||||
Vagrantfile or if the virtual machine is not currently running. Please
|
||||
check that the virtual machine is running and try again.
|
||||
missing_capability: |-
|
||||
The %{provider} provider does not support listing forwarded ports. This is
|
||||
most likely a limitation of the provider and not a bug in Vagrant. If you
|
||||
believe this is a bug in Vagrant, please search existing issues before
|
||||
opening a new one.
|
||||
no_matching_port: |-
|
||||
The guest is not currently mapping port %{port} to the host machine. Is
|
||||
the port configured in the Vagrantfile? You may need to run `vagrant reload`
|
||||
if changes were made to the port configuration in the Vagrantfile.
|
|
@ -0,0 +1,27 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPort
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "port command"
|
||||
description <<-DESC
|
||||
The `port` command displays guest port mappings.
|
||||
DESC
|
||||
|
||||
command("port") do
|
||||
require_relative "command"
|
||||
self.init!
|
||||
Command
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.init!
|
||||
return if defined?(@_init)
|
||||
I18n.load_path << File.expand_path("../locales/en.yml", __FILE__)
|
||||
I18n.reload!
|
||||
@_init = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,119 @@
|
|||
require "optparse"
|
||||
|
||||
require "vagrant/util/powershell"
|
||||
require_relative "../../communicators/winrm/helper"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPS
|
||||
class Command < Vagrant.plugin("2", :command)
|
||||
def self.synopsis
|
||||
"connects to machine via powershell remoting"
|
||||
end
|
||||
|
||||
def execute
|
||||
options = {}
|
||||
|
||||
opts = OptionParser.new do |o|
|
||||
o.banner = "Usage: vagrant powershell [-- extra powershell args]"
|
||||
|
||||
o.separator ""
|
||||
o.separator "Options:"
|
||||
o.separator ""
|
||||
|
||||
o.on("-c", "--command COMMAND", "Execute a powershell command directly") do |c|
|
||||
options[:command] = c
|
||||
end
|
||||
end
|
||||
|
||||
# Parse out the extra args to send to the ps session, which
|
||||
# is everything after the "--"
|
||||
split_index = @argv.index("--")
|
||||
if split_index
|
||||
options[:extra_args] = @argv.drop(split_index + 1)
|
||||
@argv = @argv.take(split_index)
|
||||
end
|
||||
|
||||
# Parse the options and return if we don't have any target.
|
||||
argv = parse_options(opts)
|
||||
return if !argv
|
||||
|
||||
# Check if the host even supports ps remoting
|
||||
raise Errors::HostUnsupported if !@env.host.capability?(:ps_client)
|
||||
|
||||
# Execute ps session if we can
|
||||
with_target_vms(argv, single_target: true) do |machine|
|
||||
if !machine.communicate.ready?
|
||||
raise Vagrant::Errors::VMNotCreatedError
|
||||
end
|
||||
|
||||
if machine.config.vm.communicator != :winrm
|
||||
raise VagrantPlugins::CommunicatorWinRM::Errors::WinRMNotReady
|
||||
end
|
||||
|
||||
if !options[:command].nil?
|
||||
out_code = machine.communicate.execute(options[:command].dup) do |type,data|
|
||||
machine.ui.detail(data) if type == :stdout
|
||||
end
|
||||
if out_code == 0
|
||||
machine.ui.success("Command: #{options[:command]} executed succesfully with output code #{out_code}.")
|
||||
end
|
||||
next
|
||||
end
|
||||
|
||||
ps_info = VagrantPlugins::CommunicatorWinRM::Helper.winrm_info(machine)
|
||||
ps_info[:username] = machine.config.winrm.username
|
||||
ps_info[:password] = machine.config.winrm.password
|
||||
# Extra arguments if we have any
|
||||
ps_info[:extra_args] = options[:extra_args]
|
||||
|
||||
result = ready_ps_remoting_for(machine, ps_info)
|
||||
|
||||
machine.ui.detail(
|
||||
"Creating powershell session to #{ps_info[:host]}:#{ps_info[:port]}")
|
||||
machine.ui.detail("Username: #{ps_info[:username]}")
|
||||
|
||||
begin
|
||||
@env.host.capability(:ps_client, ps_info)
|
||||
ensure
|
||||
if !result["PreviousTrustedHosts"].nil?
|
||||
reset_ps_remoting_for(machine, ps_info)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def ready_ps_remoting_for(machine, ps_info)
|
||||
machine.ui.output(I18n.t("vagrant_ps.detecting"))
|
||||
script_path = File.expand_path("../scripts/enable_psremoting.ps1", __FILE__)
|
||||
args = []
|
||||
args << "-hostname" << ps_info[:host]
|
||||
args << "-port" << ps_info[:port].to_s
|
||||
args << "-username" << ps_info[:username]
|
||||
args << "-password" << ps_info[:password]
|
||||
result = Vagrant::Util::PowerShell.execute(script_path, *args)
|
||||
if result.exit_code != 0
|
||||
raise Errors::PowerShellError,
|
||||
script: script_path,
|
||||
stderr: result.stderr
|
||||
end
|
||||
|
||||
result_output = JSON.parse(result.stdout)
|
||||
raise Errors::PSRemotingUndetected if !result_output["Success"]
|
||||
result_output
|
||||
end
|
||||
|
||||
def reset_ps_remoting_for(machine, ps_info)
|
||||
machine.ui.output(I18n.t("vagrant_ps.reseting"))
|
||||
script_path = File.expand_path("../scripts/reset_trustedhosts.ps1", __FILE__)
|
||||
args = []
|
||||
args << "-hostname" << ps_info[:host]
|
||||
result = Vagrant::Util::PowerShell.execute(script_path, *args)
|
||||
if result.exit_code != 0
|
||||
raise Errors::PowerShellError,
|
||||
script: script_path,
|
||||
stderr: result.stderr
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
module VagrantPlugins
|
||||
module CommandPS
|
||||
module Errors
|
||||
# A convenient superclass for all our errors.
|
||||
class PSCommandError < Vagrant::Errors::VagrantError
|
||||
error_namespace("vagrant_ps.errors")
|
||||
end
|
||||
|
||||
class HostUnsupported < PSCommandError
|
||||
error_key(:host_unsupported)
|
||||
end
|
||||
|
||||
class PSRemotingUndetected < PSCommandError
|
||||
error_key(:ps_remoting_undetected)
|
||||
end
|
||||
|
||||
class PowerShellError < PSCommandError
|
||||
error_key(:powershell_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,30 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandPS
|
||||
autoload :Errors, File.expand_path("../errors", __FILE__)
|
||||
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "powershell command"
|
||||
description <<-DESC
|
||||
The powershell command opens a remote PowerShell session to the
|
||||
machine if it supports powershell remoting.
|
||||
DESC
|
||||
|
||||
command("powershell") do
|
||||
require_relative "command"
|
||||
init!
|
||||
Command
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def self.init!
|
||||
return if defined?(@_init)
|
||||
I18n.load_path << File.expand_path("templates/locales/command_ps.yml", Vagrant.source_root)
|
||||
I18n.reload!
|
||||
@_init = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
Param(
|
||||
[string]$hostname,
|
||||
[string]$port,
|
||||
[string]$username,
|
||||
[string]$password
|
||||
)
|
||||
# If we are in this script, we know basic winrm is working
|
||||
# If the user is not using a domain acount and chances are
|
||||
# they are not, PS Remoting will not work if the guest is not
|
||||
# listed in the trusted hosts.
|
||||
|
||||
$encrypted_password = ConvertTo-SecureString $password -asplaintext -force
|
||||
$creds = New-Object System.Management.Automation.PSCredential (
|
||||
"$hostname\\$username", $encrypted_password)
|
||||
|
||||
$result = @{
|
||||
Success = $false
|
||||
PreviousTrustedHosts = $null
|
||||
}
|
||||
try {
|
||||
invoke-command -computername $hostname `
|
||||
-Credential $creds `
|
||||
-Port $port `
|
||||
-ScriptBlock {} `
|
||||
-ErrorAction Stop
|
||||
$result.Success = $true
|
||||
} catch{}
|
||||
|
||||
if(!$result.Success) {
|
||||
$newHosts = @()
|
||||
$result.PreviousTrustedHosts=(
|
||||
Get-Item "wsman:\localhost\client\trustedhosts").Value
|
||||
$hostArray=$result.PreviousTrustedHosts.Split(",").Trim()
|
||||
if($hostArray -contains "*") {
|
||||
$result.PreviousTrustedHosts = $null
|
||||
}
|
||||
elseif(!($hostArray -contains $hostname)) {
|
||||
$strNewHosts = $hostname
|
||||
if($result.PreviousTrustedHosts.Length -gt 0){
|
||||
$strNewHosts = $result.PreviousTrustedHosts + "," + $strNewHosts
|
||||
}
|
||||
Set-Item -Path "wsman:\localhost\client\trustedhosts" `
|
||||
-Value $strNewHosts -Force
|
||||
|
||||
try {
|
||||
invoke-command -computername $hostname `
|
||||
-Credential $creds `
|
||||
-Port $port `
|
||||
-ScriptBlock {} `
|
||||
-ErrorAction Stop
|
||||
$result.Success = $true
|
||||
} catch{
|
||||
Set-Item -Path "wsman:\localhost\client\trustedhosts" `
|
||||
-Value $result.PreviousTrustedHosts -Force
|
||||
$result.PreviousTrustedHosts = $null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output $(ConvertTo-Json $result)
|
|
@ -0,0 +1,12 @@
|
|||
Param(
|
||||
[string]$hostname
|
||||
)
|
||||
|
||||
$trustedHosts = (
|
||||
Get-Item "wsman:\localhost\client\trustedhosts").Value.Replace(
|
||||
$hostname, '')
|
||||
$trustedHosts = $trustedHosts.Replace(",,","")
|
||||
if($trustedHosts.EndsWith(",")){
|
||||
$trustedHosts = $trustedHosts.Substring(0,$trustedHosts.length-1)
|
||||
}
|
||||
Set-Item "wsman:\localhost\client\trustedhosts" -Value $trustedHosts -Force
|
|
@ -15,7 +15,7 @@ module VagrantPlugins
|
|||
o.banner = "Usage: vagrant provision [vm-name] [--provision-with x,y,z]"
|
||||
|
||||
o.on("--provision-with x,y,z", Array,
|
||||
"Enable only certain provisioners, by type.") do |list|
|
||||
"Enable only certain provisioners, by type or by name.") do |list|
|
||||
options[:provision_types] = list.map { |type| type.to_sym }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,7 +30,7 @@ module VagrantPlugins
|
|||
return if !argv
|
||||
|
||||
# Validate the provisioners
|
||||
validate_provisioner_flags!(options)
|
||||
validate_provisioner_flags!(options, argv)
|
||||
|
||||
@logger.debug("'reload' each target VM...")
|
||||
machines = []
|
||||
|
|
|
@ -41,12 +41,15 @@ module VagrantPlugins
|
|||
forward_agent: ssh_info[:forward_agent],
|
||||
forward_x11: ssh_info[:forward_x11],
|
||||
proxy_command: ssh_info[:proxy_command],
|
||||
ssh_command: ssh_info[:ssh_command]
|
||||
ssh_command: ssh_info[:ssh_command],
|
||||
forward_env: ssh_info[:forward_env],
|
||||
}
|
||||
|
||||
# Render the template and output directly to STDOUT
|
||||
template = "commands/ssh_config/config"
|
||||
safe_puts(Vagrant::Util::TemplateRenderer.render(template, variables))
|
||||
config = Vagrant::Util::TemplateRenderer.render(template, variables)
|
||||
machine.ui.machine("ssh-config", config)
|
||||
safe_puts(config)
|
||||
safe_puts
|
||||
end
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module VagrantPlugins
|
|||
return if !argv
|
||||
|
||||
# Validate the provisioners
|
||||
validate_provisioner_flags!(options)
|
||||
validate_provisioner_flags!(options, argv)
|
||||
|
||||
# Go over each VM and bring it up
|
||||
@logger.debug("'Up' each target VM...")
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require "set"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommandUp
|
||||
module StartMixins
|
||||
|
@ -17,7 +19,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
parser.on("--provision-with x,y,z", Array,
|
||||
"Enable only certain provisioners, by type.") do |list|
|
||||
"Enable only certain provisioners, by type or by name.") do |list|
|
||||
options[:provision_types] = list.map { |type| type.to_sym }
|
||||
options[:provision_enabled] = true
|
||||
options[:provision_ignore_sentinel] = true
|
||||
|
@ -26,13 +28,26 @@ module VagrantPlugins
|
|||
|
||||
# This validates the provisioner flags and raises an exception
|
||||
# if there are invalid ones.
|
||||
def validate_provisioner_flags!(options)
|
||||
(options[:provision_types] || []).each do |type|
|
||||
klass = Vagrant.plugin("2").manager.provisioners[type]
|
||||
if !klass
|
||||
raise Vagrant::Errors::ProvisionerFlagInvalid,
|
||||
name: type.to_s
|
||||
end
|
||||
def validate_provisioner_flags!(options, argv)
|
||||
if options[:provision_types].nil?
|
||||
return
|
||||
end
|
||||
|
||||
provisioner_names = Set.new
|
||||
with_target_vms(argv) do |machine|
|
||||
machine.config.vm.provisioners.map(&:name).each do |name|
|
||||
provisioner_names.add(name)
|
||||
end
|
||||
end
|
||||
|
||||
if (provisioner_names & options[:provision_types]).empty?
|
||||
(options[:provision_types] || []).each do |type|
|
||||
klass = Vagrant.plugin("2").manager.provisioners[type]
|
||||
if !klass
|
||||
raise Vagrant::Errors::ProvisionerFlagInvalid,
|
||||
name: type.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -333,6 +333,7 @@ module VagrantPlugins
|
|||
auth_methods: auth_methods,
|
||||
config: false,
|
||||
forward_agent: ssh_info[:forward_agent],
|
||||
send_env: ssh_info[:forward_env],
|
||||
keys: ssh_info[:private_key_path],
|
||||
keys_only: true,
|
||||
paranoid: false,
|
||||
|
@ -420,7 +421,7 @@ module VagrantPlugins
|
|||
rescue Errno::EHOSTDOWN
|
||||
# This is raised if we get an ICMP DestinationUnknown error.
|
||||
raise Vagrant::Errors::SSHHostDown
|
||||
rescue Errno::EHOSTUNREACH
|
||||
rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
|
||||
# This is raised if we can't work out how to route traffic.
|
||||
raise Vagrant::Errors::SSHNoRoute
|
||||
rescue Net::SSH::Exception => e
|
||||
|
@ -611,6 +612,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
data = pty_stdout[/.*#{PTY_DELIM_START}(.*?)#{PTY_DELIM_END}/m, 1]
|
||||
data ||= ""
|
||||
@logger.debug("PTY stdout parsed: #{data}")
|
||||
yield :stdout, data if block_given?
|
||||
end
|
||||
|
|
|
@ -43,6 +43,7 @@ module VagrantPlugins
|
|||
# Got it! Let the user know what we're connecting to.
|
||||
@machine.ui.detail("WinRM address: #{shell.host}:#{shell.port}")
|
||||
@machine.ui.detail("WinRM username: #{shell.username}")
|
||||
@machine.ui.detail("WinRM execution_time_limit: #{shell.execution_time_limit}")
|
||||
@machine.ui.detail("WinRM transport: #{shell.config.transport}")
|
||||
|
||||
last_message = nil
|
||||
|
@ -136,10 +137,11 @@ module VagrantPlugins
|
|||
error_key: nil, # use the error_class message key
|
||||
good_exit: 0,
|
||||
shell: :powershell,
|
||||
interactive: false,
|
||||
}.merge(opts || {})
|
||||
|
||||
opts[:good_exit] = Array(opts[:good_exit])
|
||||
command = wrap_in_scheduled_task(command) if opts[:elevated]
|
||||
command = wrap_in_scheduled_task(command, opts[:interactive]) if opts[:elevated]
|
||||
output = shell.send(opts[:shell], command, &block)
|
||||
execution_output(output, opts)
|
||||
end
|
||||
|
@ -193,9 +195,11 @@ module VagrantPlugins
|
|||
# in place.
|
||||
#
|
||||
# @return The wrapper command to execute
|
||||
def wrap_in_scheduled_task(command)
|
||||
def wrap_in_scheduled_task(command, interactive)
|
||||
path = File.expand_path("../scripts/elevated_shell.ps1", __FILE__)
|
||||
script = Vagrant::Util::TemplateRenderer.render(path)
|
||||
script = Vagrant::Util::TemplateRenderer.render(path, options: {
|
||||
interactive: interactive,
|
||||
})
|
||||
guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1"
|
||||
file = Tempfile.new(["vagrant-elevated-shell", "ps1"])
|
||||
begin
|
||||
|
@ -208,14 +212,16 @@ module VagrantPlugins
|
|||
file.unlink
|
||||
end
|
||||
|
||||
# convert to double byte unicode string then base64 encode
|
||||
# just like PowerShell -EncodedCommand expects
|
||||
# Convert to double byte unicode string then base64 encode
|
||||
# just like PowerShell -EncodedCommand expects.
|
||||
# Suppress the progress stream from leaking to stderr.
|
||||
wrapped_encoded_command = Base64.strict_encode64(
|
||||
"#{command}; exit $LASTEXITCODE".encode('UTF-16LE', 'UTF-8'))
|
||||
"$ProgressPreference='SilentlyContinue'; #{command}; exit $LASTEXITCODE".encode('UTF-16LE', 'UTF-8'))
|
||||
|
||||
"powershell -executionpolicy bypass -file \"#{guest_script_path}\" " +
|
||||
"-username \"#{shell.username}\" -password \"#{shell.password}\" " +
|
||||
"-encoded_command \"#{wrapped_encoded_command}\""
|
||||
"powershell -executionpolicy bypass -file '#{guest_script_path}' " +
|
||||
"-username '#{shell.username}' -password '#{shell.password}' " +
|
||||
"-encoded_command '#{wrapped_encoded_command}' " +
|
||||
"-execution_time_limit '#{shell.execution_time_limit}'"
|
||||
end
|
||||
|
||||
# Handles the raw WinRM shell result and converts it to a
|
||||
|
|
|
@ -11,6 +11,7 @@ module VagrantPlugins
|
|||
attr_accessor :timeout
|
||||
attr_accessor :transport
|
||||
attr_accessor :ssl_peer_verification
|
||||
attr_accessor :execution_time_limit
|
||||
|
||||
def initialize
|
||||
@username = UNSET_VALUE
|
||||
|
@ -23,6 +24,7 @@ module VagrantPlugins
|
|||
@timeout = UNSET_VALUE
|
||||
@transport = UNSET_VALUE
|
||||
@ssl_peer_verification = UNSET_VALUE
|
||||
@execution_time_limit = UNSET_VALUE
|
||||
end
|
||||
|
||||
def finalize!
|
||||
|
@ -37,6 +39,7 @@ module VagrantPlugins
|
|||
@retry_delay = 2 if @retry_delay == UNSET_VALUE
|
||||
@timeout = 1800 if @timeout == UNSET_VALUE
|
||||
@ssl_peer_verification = true if @ssl_peer_verification == UNSET_VALUE
|
||||
@execution_time_limit = "PT2H" if @execution_time_limit == UNSET_VALUE
|
||||
end
|
||||
|
||||
def validate(machine)
|
||||
|
@ -49,6 +52,7 @@ module VagrantPlugins
|
|||
errors << "winrm.max_tries cannot be nil." if @max_tries.nil?
|
||||
errors << "winrm.retry_delay cannot be nil." if @max_tries.nil?
|
||||
errors << "winrm.timeout cannot be nil." if @timeout.nil?
|
||||
errors << "winrm.execution_time_limit cannot be nil." if @execution_time_limit.nil?
|
||||
unless @ssl_peer_verification == true || @ssl_peer_verification == false
|
||||
errors << "winrm.ssl_peer_verification must be a boolean."
|
||||
end
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
param([String]$username, [String]$password, [String]$encoded_command)
|
||||
param([String]$username, [String]$password, [String]$encoded_command, [String]$execution_time_limit)
|
||||
|
||||
# Try to get the Schedule.Service object. If it fails, we are probably
|
||||
# on an older version of Windows. On old versions, we can just execute
|
||||
# directly since priv. escalation isn't a thing.
|
||||
$schedule = $null
|
||||
Try {
|
||||
$schedule = New-Object -ComObject "Schedule.Service"
|
||||
} Catch [System.Management.Automation.PSArgumentException] {
|
||||
powershell.exe -EncodedCommand $encoded_command
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
$task_name = "WinRM_Elevated_Shell"
|
||||
$out_file = "$env:SystemRoot\Temp\WinRM_Elevated_Shell.log"
|
||||
|
||||
|
@ -13,7 +25,7 @@ $task_xml = @'
|
|||
<Principals>
|
||||
<Principal id="Author">
|
||||
<UserId>{username}</UserId>
|
||||
<LogonType>Password</LogonType>
|
||||
<LogonType><%= options[:interactive] ? 'InteractiveTokenOrPassword' : 'Password' %></LogonType>
|
||||
<RunLevel>HighestAvailable</RunLevel>
|
||||
</Principal>
|
||||
</Principals>
|
||||
|
@ -33,7 +45,7 @@ $task_xml = @'
|
|||
<Hidden>false</Hidden>
|
||||
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
||||
<WakeToRun>false</WakeToRun>
|
||||
<ExecutionTimeLimit>PT2H</ExecutionTimeLimit>
|
||||
<ExecutionTimeLimit>{execution_time_limit}</ExecutionTimeLimit>
|
||||
<Priority>4</Priority>
|
||||
</Settings>
|
||||
<Actions Context="Author">
|
||||
|
@ -49,13 +61,13 @@ $arguments = "/c powershell.exe -EncodedCommand $encoded_command > $out_file
|
|||
|
||||
$task_xml = $task_xml.Replace("{arguments}", $arguments)
|
||||
$task_xml = $task_xml.Replace("{username}", $username)
|
||||
$task_xml = $task_xml.Replace("{execution_time_limit}", $execution_time_limit)
|
||||
|
||||
$schedule = New-Object -ComObject "Schedule.Service"
|
||||
$schedule.Connect()
|
||||
$task = $schedule.NewTask($null)
|
||||
$task.XmlText = $task_xml
|
||||
$folder = $schedule.GetFolder("\")
|
||||
$folder.RegisterTaskDefinition($task_name, $task, 6, $username, $password, 1, $null) | Out-Null
|
||||
$folder.RegisterTaskDefinition($task_name, $task, 6, $username, $password, <%= options[:interactive] ? 3 : 1 %>, $null) | Out-Null
|
||||
|
||||
$registered_task = $folder.GetTask("\$task_name")
|
||||
$registered_task.Run($null) | Out-Null
|
||||
|
@ -71,7 +83,7 @@ function SlurpOutput($out_file, $cur_line) {
|
|||
if (Test-Path $out_file) {
|
||||
get-content $out_file | select -skip $cur_line | ForEach {
|
||||
$cur_line += 1
|
||||
Write-Host "$_"
|
||||
Write-Host "$_"
|
||||
}
|
||||
}
|
||||
return $cur_line
|
||||
|
|
|
@ -9,7 +9,7 @@ Vagrant::Util::SilenceWarnings.silence! do
|
|||
require "winrm"
|
||||
end
|
||||
|
||||
require "winrm-fs/file_manager"
|
||||
require "winrm-fs"
|
||||
|
||||
module VagrantPlugins
|
||||
module CommunicatorWinRM
|
||||
|
@ -23,6 +23,7 @@ module VagrantPlugins
|
|||
HTTPClient::KeepAliveDisconnected,
|
||||
WinRM::WinRMHTTPTransportError,
|
||||
WinRM::WinRMAuthorizationError,
|
||||
WinRM::WinRMWSManFault,
|
||||
Errno::EACCES,
|
||||
Errno::EADDRINUSE,
|
||||
Errno::ECONNREFUSED,
|
||||
|
@ -37,6 +38,7 @@ module VagrantPlugins
|
|||
attr_reader :port
|
||||
attr_reader :username
|
||||
attr_reader :password
|
||||
attr_reader :execution_time_limit
|
||||
attr_reader :config
|
||||
|
||||
def initialize(host, port, config)
|
||||
|
@ -47,12 +49,15 @@ module VagrantPlugins
|
|||
@port = port
|
||||
@username = config.username
|
||||
@password = config.password
|
||||
@execution_time_limit = config.execution_time_limit
|
||||
@config = config
|
||||
end
|
||||
|
||||
def powershell(command, &block)
|
||||
# ensure an exit code
|
||||
# Suppress the progress stream from leaking to stderr
|
||||
command = "$ProgressPreference='SilentlyContinue';\r\n" + command
|
||||
command << "\r\n"
|
||||
# Ensure an exit code
|
||||
command << "if ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
|
||||
execute_shell(command, :powershell, &block)
|
||||
end
|
||||
|
|
|
@ -27,7 +27,7 @@ module VagrantPlugins
|
|||
|
||||
machine.communicate.upload(temp.path, "/tmp/vagrant_network")
|
||||
machine.communicate.sudo("mv /tmp/vagrant_network /etc/netctl/#{network[:device]}")
|
||||
machine.communicate.sudo("ip link set #{network[:device]} down && netctl start #{network[:device]}")
|
||||
machine.communicate.sudo("ip link set #{network[:device]} down && netctl start #{network[:device]} && netctl enable #{network[:device]}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,45 +6,109 @@ module VagrantPlugins
|
|||
module GuestDarwin
|
||||
module Cap
|
||||
class ConfigureNetworks
|
||||
@@logger = Log4r::Logger.new("vagrant::guest::darwin::configure_networks")
|
||||
|
||||
include Vagrant::Util
|
||||
|
||||
def self.configure_networks(machine, networks)
|
||||
# Slightly different than other plugins, using the template to build commands
|
||||
# rather than templating the files.
|
||||
if !machine.provider.capability?(:nic_mac_addresses)
|
||||
raise Vagrant::Errors::CantReadMACAddresses,
|
||||
provider: machine.provider_name.to_s
|
||||
end
|
||||
|
||||
machine.communicate.sudo("networksetup -detectnewhardware")
|
||||
machine.communicate.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces")
|
||||
tmpints = File.join(Dir.tmpdir, File.basename("#{machine.id}.interfaces"))
|
||||
machine.communicate.download("/tmp/vagrant.interfaces",tmpints)
|
||||
nic_mac_addresses = machine.provider.capability(:nic_mac_addresses)
|
||||
@@logger.debug("mac addresses: #{nic_mac_addresses.inspect}")
|
||||
|
||||
devlist = []
|
||||
ints = ::IO.read(tmpints)
|
||||
mac_service_map = create_mac_service_map(machine)
|
||||
|
||||
networks.each do |network|
|
||||
mac_address = nic_mac_addresses[network[:interface]+1]
|
||||
if mac_address.nil?
|
||||
@@logger.warn("Could not find mac address for network #{network.inspect}")
|
||||
next
|
||||
end
|
||||
|
||||
service_name = mac_service_map[mac_address]
|
||||
if service_name.nil?
|
||||
@@logger.warn("Could not find network service for mac address #{mac_address}")
|
||||
next
|
||||
end
|
||||
|
||||
network_type = network[:type].to_sym
|
||||
if network_type == :static
|
||||
command = "networksetup -setmanual \"#{service_name}\" #{network[:ip]} #{network[:netmask]}"
|
||||
elsif network_type == :dhcp
|
||||
command = "networksetup -setdhcp \"#{service_name}\""
|
||||
else
|
||||
raise "#{network_type} network type is not supported, try static or dhcp"
|
||||
end
|
||||
|
||||
machine.communicate.sudo(command)
|
||||
end
|
||||
end
|
||||
|
||||
# Creates a hash mapping MAC addresses to network service name
|
||||
# Example: { "00C100A1B2C3" => "Thunderbolt Ethernet" }
|
||||
def self.create_mac_service_map(machine)
|
||||
tmp_ints = File.join(Dir.tmpdir, File.basename("#{machine.id}.interfaces"))
|
||||
tmp_hw = File.join(Dir.tmpdir, File.basename("#{machine.id}.hardware"))
|
||||
|
||||
machine.communicate.tap do |comm|
|
||||
comm.sudo("networksetup -detectnewhardware")
|
||||
comm.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces")
|
||||
comm.sudo("networksetup -listallhardwareports > /tmp/vagrant.hardware")
|
||||
comm.download("/tmp/vagrant.interfaces", tmp_ints)
|
||||
comm.download("/tmp/vagrant.hardware", tmp_hw)
|
||||
end
|
||||
|
||||
interface_map = {}
|
||||
ints = ::IO.read(tmp_ints)
|
||||
ints.split(/\n\n/m).each do |i|
|
||||
if i.match(/Hardware/) and not i.match(/Ethernet/).nil?
|
||||
devmap = {}
|
||||
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||
# Ethernet, should be 2 lines,
|
||||
# (3) Thunderbolt Ethernet
|
||||
# (Hardware Port: Thunderbolt Ethernet, Device: en1)
|
||||
|
||||
# multiline, should match "Thunderbolt Ethernet", "en1"
|
||||
devicearry = i.match(/\([0-9]+\) (.+)\n.*Device: (.+)\)/m)
|
||||
devmap[:interface] = devicearry[2]
|
||||
devmap[:service] = devicearry[1]
|
||||
devlist << devmap
|
||||
service = devicearry[1]
|
||||
interface = devicearry[2]
|
||||
|
||||
# Should map interface to service { "en1" => "Thunderbolt Ethernet" }
|
||||
interface_map[interface] = service
|
||||
end
|
||||
end
|
||||
File.delete(tmpints)
|
||||
File.delete(tmp_ints)
|
||||
|
||||
networks.each do |network|
|
||||
service_name = devlist[network[:interface]][:service]
|
||||
if network[:type].to_sym == :static
|
||||
command = "networksetup -setmanual \"#{service_name}\" #{network[:ip]} #{network[:netmask]}"
|
||||
elsif network[:type].to_sym == :dhcp
|
||||
command = "networksetup -setdhcp \"#{service_name}\""
|
||||
mac_service_map = {}
|
||||
macs = ::IO.read(tmp_hw)
|
||||
macs.split(/\n\n/m).each do |i|
|
||||
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||
# Ethernet, should be 3 lines,
|
||||
# Hardware Port: Thunderbolt 1
|
||||
# Device: en1
|
||||
# Ethernet Address: a1:b2:c3:d4:e5:f6
|
||||
|
||||
# multiline, should match "en1", "00:c1:00:a1:b2:c3"
|
||||
devicearry = i.match(/Device: (.+)\nEthernet Address: (.+)/m)
|
||||
interface = devicearry[1]
|
||||
naked_mac = devicearry[2].gsub(':','').upcase
|
||||
|
||||
# Skip hardware ports without MAC (bridges, bluetooth, etc.)
|
||||
next if naked_mac == "N/A"
|
||||
|
||||
if !interface_map[interface]
|
||||
@@logger.warn("Could not find network service for interface #{interface}")
|
||||
next
|
||||
end
|
||||
|
||||
# Should map MAC to service, { "00C100A1B2C3" => "Thunderbolt Ethernet" }
|
||||
mac_service_map[naked_mac] = interface_map[interface]
|
||||
end
|
||||
|
||||
machine.communicate.sudo(command)
|
||||
end
|
||||
File.delete(tmp_hw)
|
||||
|
||||
mac_service_map
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
module VagrantPlugins
|
||||
module GuestDebian
|
||||
module Cap
|
||||
class SMB
|
||||
def self.smb_install(machine)
|
||||
# Deb/Ubuntu require mount.cifs which doesn't come by default.
|
||||
machine.communicate.tap do |comm|
|
||||
if !comm.test("test -f /sbin/mount.cifs")
|
||||
machine.ui.detail(I18n.t("vagrant.guest_deb_installing_smb"))
|
||||
comm.sudo("apt-get -y update")
|
||||
comm.sudo("apt-get -y install cifs-utils")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,7 +2,7 @@ module VagrantPlugins
|
|||
module GuestDebian
|
||||
class Guest < Vagrant.plugin("2", :guest)
|
||||
def detect?(machine)
|
||||
machine.communicate.test("cat /etc/issue | grep 'Debian' | grep -v '8'")
|
||||
machine.communicate.test("cat /etc/issue | grep 'Debian'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,6 +30,11 @@ module VagrantPlugins
|
|||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability("debian", "smb_install") do
|
||||
require_relative "cap/smb"
|
||||
Cap::SMB
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
module VagrantPlugins
|
||||
module GuestDebian8
|
||||
module Cap
|
||||
class Halt
|
||||
def self.halt(machine)
|
||||
begin
|
||||
machine.communicate.sudo("shutdown -h -H")
|
||||
rescue IOError
|
||||
# Do nothing, because it probably means the machine shut down
|
||||
# and SSH connection was lost.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestDebian8
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "Debian Jessie guest"
|
||||
description "Debian Jessie guest support."
|
||||
|
||||
guest("debian8", "debian") do
|
||||
require File.expand_path("../guest", __FILE__)
|
||||
Guest
|
||||
end
|
||||
|
||||
guest_capability("debian8", "halt") do
|
||||
require_relative "cap/halt"
|
||||
Cap::Halt
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -48,7 +48,7 @@ module VagrantPlugins
|
|||
def update_etc_hosts
|
||||
ip_address = '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||
search = "^(#{ip_address})\\s+#{Regexp.escape(current_hostname)}(\\s.*)?$"
|
||||
replace = "\\1 #{fqdn} #{short_hostname}"
|
||||
replace = "\\1 #{fqdn} #{short_hostname} \\3"
|
||||
expression = ['s', search, replace, 'g'].join('@')
|
||||
|
||||
sudo("sed -ri '#{expression}' /etc/hosts")
|
||||
|
@ -72,4 +72,4 @@ module VagrantPlugins
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -109,13 +109,23 @@ module VagrantPlugins
|
|||
# SSH never dies.
|
||||
interfaces.each do |interface|
|
||||
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("! which nmcli >/dev/null 2>&1 || nmcli c reload #{interface}")
|
||||
machine.communicate.sudo("/sbin/ifdown #{interface}", error_check: true)
|
||||
machine.communicate.sudo("/sbin/ifup #{interface}")
|
||||
end
|
||||
machine.communicate.sudo(<<-SCRIPT, error_check: true)
|
||||
cat /tmp/vagrant-network-entry_#{interface} >> #{network_scripts_dir}/ifcfg-#{interface}
|
||||
|
||||
machine.communicate.sudo("rm -f /tmp/vagrant-network-entry_#{interface}")
|
||||
if command -v nmcli &>/dev/null; then
|
||||
if command -v systemctl &>/dev/null && systemctl -q is-enabled NetworkManager &>/dev/null; then
|
||||
nmcli c reload #{interface}
|
||||
elif command -v service &>/dev/null && service NetworkManager status &>/dev/null; then
|
||||
nmcli c reload #{interface}
|
||||
fi
|
||||
fi
|
||||
|
||||
/sbin/ifdown #{interface}
|
||||
/sbin/ifup #{interface}
|
||||
|
||||
rm -f /tmp/vagrant-network-entry_#{interface}
|
||||
SCRIPT
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ module VagrantPlugins
|
|||
module GuestFedora
|
||||
class Guest < Vagrant.plugin("2", :guest)
|
||||
def detect?(machine)
|
||||
machine.communicate.test("grep 'Fedora release 1[6789]\\|Fedora release 2[0-9]' /etc/redhat-release")
|
||||
machine.communicate.test("grep 'Fedora release' /etc/redhat-release")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,10 +33,11 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
# Emit an upstart event if we can
|
||||
if machine.communicate.test("test -x /sbin/initctl && test 'upstart' = $(basename $(sudo readlink /proc/1/exe))")
|
||||
machine.communicate.sudo(
|
||||
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}")
|
||||
end
|
||||
machine.communicate.sudo <<-SCRIPT
|
||||
if command -v /sbin/init &>/dev/null && /sbin/init --version | grep upstart &>/dev/null; then
|
||||
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||
fi
|
||||
SCRIPT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,17 +24,14 @@ module VagrantPlugins
|
|||
mount_gid = "`getent group #{options[:group]} | cut -d: -f3`"
|
||||
mount_gid_old = "`id -g #{options[:group]}`"
|
||||
end
|
||||
|
||||
smb_password = Shellwords.shellescape(options[:smb_password])
|
||||
|
||||
|
||||
# If a domain is provided in the username, separate it
|
||||
username, domain = (options[:smb_username] || '').split('@', 2)
|
||||
smb_password = options[:smb_password]
|
||||
|
||||
options[:mount_options] ||= []
|
||||
options[:mount_options] << "sec=ntlm"
|
||||
options[:mount_options] << "username=#{username}"
|
||||
options[:mount_options] << "password=#{smb_password}"
|
||||
options[:mount_options] << "domain=#{domain}" if domain
|
||||
options[:mount_options] << "credentials=/etc/smb_creds_#{name}"
|
||||
|
||||
# First mount command uses getent to get the group
|
||||
mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"
|
||||
|
@ -49,6 +46,16 @@ module VagrantPlugins
|
|||
# Create the guest path if it doesn't exist
|
||||
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
||||
|
||||
# Write the credentials file
|
||||
machine.communicate.sudo(<<-SCRIPT)
|
||||
cat <<EOF >/etc/smb_creds_#{name}
|
||||
username=#{username}
|
||||
password=#{smb_password}
|
||||
#{domain ? "domain=#{domain}" : ""}
|
||||
EOF
|
||||
chmod 0600 /etc/smb_creds_#{name}
|
||||
SCRIPT
|
||||
|
||||
# Attempt to mount the folder. We retry here a few times because
|
||||
# it can fail early on.
|
||||
attempts = 0
|
||||
|
@ -86,10 +93,11 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
# Emit an upstart event if we can
|
||||
if machine.communicate.test("test -x /sbin/initctl && test 'upstart' = $(basename $(sudo readlink /proc/1/exe))")
|
||||
machine.communicate.sudo(
|
||||
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}")
|
||||
end
|
||||
machine.communicate.sudo <<-SCRIPT
|
||||
if command -v /sbin/init &>/dev/null && /sbin/init --version | grep upstart &>/dev/null; then
|
||||
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||
fi
|
||||
SCRIPT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -80,10 +80,11 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
# Emit an upstart event if we can
|
||||
if machine.communicate.test("test -x /sbin/initctl && test 'upstart' = $(basename $(sudo readlink /proc/1/exe))")
|
||||
machine.communicate.sudo(
|
||||
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{expanded_guest_path}")
|
||||
end
|
||||
machine.communicate.sudo <<-SCRIPT
|
||||
if command -v /sbin/init &>/dev/null && /sbin/init --version | grep upstart &>/dev/null; then
|
||||
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||
fi
|
||||
SCRIPT
|
||||
end
|
||||
|
||||
def self.unmount_virtualbox_shared_folder(machine, guestpath, options)
|
||||
|
|
|
@ -10,8 +10,11 @@ module VagrantPlugins
|
|||
|
||||
machine.communicate.tap do |comm|
|
||||
if comm.test("test -f ~/.ssh/authorized_keys")
|
||||
comm.execute(
|
||||
"sed -i '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys")
|
||||
comm.execute(<<SCRIPT)
|
||||
sed -e '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.new
|
||||
mv ~/.ssh/authorized_keys.new ~/.ssh/authorized_keys
|
||||
chmod 600 ~/.ssh/authorized_keys
|
||||
SCRIPT
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
module VagrantPlugins
|
||||
module GuestPld
|
||||
module Cap
|
||||
class Flavor
|
||||
def self.flavor(machine)
|
||||
return :pld
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -20,6 +20,11 @@ module VagrantPlugins
|
|||
require_relative "cap/network_scripts_dir"
|
||||
Cap::NetworkScriptsDir
|
||||
end
|
||||
|
||||
guest_capability("pld", "flavor") do
|
||||
require_relative "cap/flavor"
|
||||
Cap::Flavor
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,11 @@ module VagrantPlugins
|
|||
module Cap
|
||||
class NFSClient
|
||||
def self.nfs_client_install(machine)
|
||||
machine.communicate.sudo("yum -y install nfs-utils nfs-utils-lib")
|
||||
if VagrantPlugins::GuestRedHat::Plugin.dnf?(machine)
|
||||
machine.communicate.sudo("dnf -y install nfs-utils nfs-utils-lib")
|
||||
else
|
||||
machine.communicate.sudo("yum -y install nfs-utils nfs-utils-lib")
|
||||
end
|
||||
restart_nfs(machine)
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,11 @@ module VagrantPlugins
|
|||
class RSync
|
||||
def self.rsync_install(machine)
|
||||
machine.communicate.tap do |comm|
|
||||
comm.sudo("yum -y install rsync")
|
||||
if VagrantPlugins::GuestRedHat::Plugin.dnf?(machine)
|
||||
comm.sudo("dnf -y install rsync")
|
||||
else
|
||||
comm.sudo("yum -y install rsync")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,6 +45,10 @@ module VagrantPlugins
|
|||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
def self.dnf?(machine)
|
||||
machine.communicate.test("/usr/bin/which -s dnf")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
module VagrantPlugins
|
||||
module GuestSlackware
|
||||
module Cap
|
||||
class ChangeHostName
|
||||
def self.change_host_name(machine, name)
|
||||
machine.communicate.tap do |comm|
|
||||
# Only do this if the hostname is not already set
|
||||
if !comm.test("sudo hostname | grep '#{name}'")
|
||||
comm.sudo("chmod o+w /etc/hostname")
|
||||
comm.sudo("echo #{name} > /etc/hostname")
|
||||
comm.sudo("chmod o-w /etc/hostname")
|
||||
comm.sudo("hostname -F /etc/hostname")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
require "tempfile"
|
||||
|
||||
require "vagrant/util/template_renderer"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestSlackware
|
||||
module Cap
|
||||
class ConfigureNetworks
|
||||
include Vagrant::Util
|
||||
|
||||
def self.configure_networks(machine, networks)
|
||||
interfaces = Array.new
|
||||
machine.communicate.sudo("ip -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'") do |_, result|
|
||||
interfaces = result.split("\n")
|
||||
end
|
||||
|
||||
networks.each do |network|
|
||||
network[:device] = interfaces[network[:interface]]
|
||||
|
||||
entry = TemplateRenderer.render("guests/slackware/network_#{network[:type]}", options: network)
|
||||
|
||||
temp = Tempfile.new("vagrant")
|
||||
temp.binmode
|
||||
temp.write(entry)
|
||||
temp.close
|
||||
|
||||
machine.communicate.upload(temp.path, "/tmp/vagrant_network")
|
||||
machine.communicate.sudo("mv /tmp/vagrant_network /etc/rc.d/rc.inet1.conf")
|
||||
machine.communicate.sudo("/etc/rc.d/rc.inet1")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,8 +1,10 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestDebian8
|
||||
module GuestSlackware
|
||||
class Guest < Vagrant.plugin("2", :guest)
|
||||
def detect?(machine)
|
||||
machine.communicate.test("cat /etc/issue | grep 'Debian' | grep '8'")
|
||||
machine.communicate.test("cat /etc/slackware-version")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
require "vagrant"
|
||||
|
||||
module VagrantPlugins
|
||||
module GuestSlackware
|
||||
class Plugin < Vagrant.plugin("2")
|
||||
name "Slackware guest"
|
||||
description "Slackware guest support."
|
||||
|
||||
guest("slackware", "linux") do
|
||||
require File.expand_path("../guest", __FILE__)
|
||||
Guest
|
||||
end
|
||||
|
||||
guest_capability("slackware", "change_host_name") do
|
||||
require_relative "cap/change_host_name"
|
||||
Cap::ChangeHostName
|
||||
end
|
||||
|
||||
guest_capability("slackware", "configure_networks") do
|
||||
require_relative "cap/configure_networks"
|
||||
Cap::ConfigureNetworks
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,7 +7,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def update_etc_hostname
|
||||
return super unless vivid?
|
||||
return super unless systemd?
|
||||
sudo("hostnamectl set-hostname '#{short_hostname}'")
|
||||
end
|
||||
|
||||
|
@ -15,7 +15,7 @@ module VagrantPlugins
|
|||
if hardy?
|
||||
# hostname.sh returns 1, so use `true` to get a 0 exitcode
|
||||
sudo("/etc/init.d/hostname.sh start; true")
|
||||
elsif vivid?
|
||||
elsif systemd?
|
||||
# Service runs via hostnamectl
|
||||
else
|
||||
sudo("service hostname start")
|
||||
|
@ -26,19 +26,25 @@ module VagrantPlugins
|
|||
os_version("hardy")
|
||||
end
|
||||
|
||||
def vivid?
|
||||
os_version("vivid")
|
||||
end
|
||||
|
||||
def renew_dhcp
|
||||
sudo("ifdown -a; ifup -a; ifup -a --allow=hotplug")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init_package
|
||||
machine.communicate.execute('cat /proc/1/comm') do |type, data|
|
||||
return data.chomp if type == :stdout
|
||||
end
|
||||
end
|
||||
|
||||
def os_version(name)
|
||||
machine.communicate.test("[ `lsb_release -c -s` = #{name} ]")
|
||||
end
|
||||
|
||||
def systemd?
|
||||
init_package == 'systemd'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -53,7 +53,7 @@ module VagrantPlugins
|
|||
|
||||
def self.create_vm_interface_map(machine, guest_network)
|
||||
if !machine.provider.capability?(:nic_mac_addresses)
|
||||
raise Errors::CantReadMACAddresses,
|
||||
raise Vagrant::Errors::CantReadMACAddresses,
|
||||
provider: machine.provider_name.to_s
|
||||
end
|
||||
|
||||
|
|
|
@ -2,8 +2,17 @@ module VagrantPlugins
|
|||
module GuestWindows
|
||||
module Cap
|
||||
class RSync
|
||||
def self.rsync_scrub_guestpath( machine, opts )
|
||||
# Windows guests most often use cygwin-dependent rsync utilities
|
||||
# that expect "/cygdrive/c" instead of "c:" as the path prefix
|
||||
# some vagrant code may pass guest paths with drive-lettered paths here
|
||||
opts[:guestpath].gsub( /^([a-zA-Z]):/, '/cygdrive/\1' )
|
||||
end
|
||||
|
||||
def self.rsync_pre(machine, opts)
|
||||
machine.communicate.tap do |comm|
|
||||
# rsync does not construct any gaps in the path to the target directory
|
||||
# make sure that all subdirectories are created
|
||||
comm.execute("mkdir '#{opts[:guestpath]}'")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,10 +6,6 @@ module VagrantPlugins
|
|||
error_namespace("vagrant_windows.errors")
|
||||
end
|
||||
|
||||
class CantReadMACAddresses < WindowsError
|
||||
error_key(:cant_read_mac_addresses)
|
||||
end
|
||||
|
||||
class NetworkWinRMRequired < WindowsError
|
||||
error_key(:network_winrm_required)
|
||||
end
|
||||
|
|
|
@ -64,6 +64,11 @@ module VagrantPlugins
|
|||
Cap::MountSharedFolder
|
||||
end
|
||||
|
||||
guest_capability(:windows, :rsync_scrub_guestpath) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
end
|
||||
|
||||
guest_capability(:windows, :rsync_pre) do
|
||||
require_relative "cap/rsync"
|
||||
Cap::RSync
|
||||
|
|
|
@ -2,6 +2,7 @@ require "pathname"
|
|||
require "tempfile"
|
||||
|
||||
require "vagrant/util/downloader"
|
||||
require "vagrant/util/file_checksum"
|
||||
require "vagrant/util/subprocess"
|
||||
|
||||
module VagrantPlugins
|
||||
|
@ -10,8 +11,9 @@ module VagrantPlugins
|
|||
class ProviderInstallVirtualBox
|
||||
# The URL to download VirtualBox is hardcoded so we can have a
|
||||
# known-good version to download.
|
||||
URL = "http://download.virtualbox.org/virtualbox/5.0.8/VirtualBox-5.0.8-103449-OSX.dmg".freeze
|
||||
VERSION = "5.0.8".freeze
|
||||
URL = "http://download.virtualbox.org/virtualbox/5.0.10/VirtualBox-5.0.10-104061-OSX.dmg".freeze
|
||||
VERSION = "5.0.10".freeze
|
||||
SHA256SUM = "62f933115498e51ddf5f2dab47dc1eebb42eb78ea1a7665cb91c53edacc847c6".freeze
|
||||
|
||||
def self.provider_install_virtualbox(env)
|
||||
tf = Tempfile.new("vagrant")
|
||||
|
@ -29,6 +31,15 @@ module VagrantPlugins
|
|||
dl = Vagrant::Util::Downloader.new(URL, tf.path, ui: ui)
|
||||
dl.download!
|
||||
|
||||
# Validate that the file checksum matches
|
||||
actual = Vagrant::Util::FileChecksum.new(tf.path, Digest::SHA2).checksum
|
||||
if actual != SHA256SUM
|
||||
raise Vagrant::Errors::ProviderChecksumMismatch,
|
||||
provider: "virtualbox",
|
||||
actual: actual,
|
||||
expected: SHA256SUM
|
||||
end
|
||||
|
||||
# Launch it
|
||||
ui.output(I18n.t(
|
||||
"vagrant.hosts.darwin.virtualbox_install_install"))
|
||||
|
|
|
@ -5,17 +5,35 @@ module VagrantPlugins
|
|||
module Cap
|
||||
class RDP
|
||||
def self.rdp_client(env, rdp_info)
|
||||
if !Vagrant::Util::Which.which("rdesktop")
|
||||
raise Vagrant::Errors::LinuxRDesktopNotFound
|
||||
end
|
||||
# Detect if an RDP client is available.
|
||||
# Prefer xfreerdp as it supports newer versions of RDP.
|
||||
rdp_client =
|
||||
if Vagrant::Util::Which.which("xfreerdp")
|
||||
"xfreerdp"
|
||||
elsif Vagrant::Util::Which.which("rdesktop")
|
||||
"rdesktop"
|
||||
else
|
||||
raise Vagrant::Errors::LinuxRDPClientNotFound
|
||||
end
|
||||
|
||||
args = []
|
||||
args << "-u" << rdp_info[:username]
|
||||
args << "-p" << rdp_info[:password] if rdp_info[:password]
|
||||
args += rdp_info[:extra_args] if rdp_info[:extra_args]
|
||||
args << "#{rdp_info[:host]}:#{rdp_info[:port]}"
|
||||
|
||||
Vagrant::Util::Subprocess.execute("rdesktop", *args)
|
||||
# Build appropriate arguments for the RDP client.
|
||||
case rdp_client
|
||||
when "xfreerdp"
|
||||
args << "/u:#{rdp_info[:username]}"
|
||||
args << "/p:#{rdp_info[:password]}" if rdp_info[:password]
|
||||
args << "/v:#{rdp_info[:host]}:#{rdp_info[:port]}"
|
||||
args += rdp_info[:extra_args] if rdp_info[:extra_args]
|
||||
when "rdesktop"
|
||||
args << "-u" << rdp_info[:username]
|
||||
args << "-p" << rdp_info[:password] if rdp_info[:password]
|
||||
args += rdp_info[:extra_args] if rdp_info[:extra_args]
|
||||
args << "#{rdp_info[:host]}:#{rdp_info[:port]}"
|
||||
end
|
||||
|
||||
# Finally, run the client.
|
||||
Vagrant::Util::Subprocess.execute(rdp_client, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ module VagrantPlugins
|
|||
module Cap
|
||||
class NFS
|
||||
def self.nfs_check_command(env)
|
||||
"pidof nfsd >/dev/null"
|
||||
"/sbin/pidof nfsd >/dev/null"
|
||||
end
|
||||
|
||||
def self.nfs_start_command(env)
|
||||
|
|
|
@ -4,7 +4,7 @@ module VagrantPlugins
|
|||
module HostSlackware
|
||||
class Host < Vagrant.plugin("2", :host)
|
||||
def detect?(env)
|
||||
return File.exists?("/etc/slackware-release") ||
|
||||
return File.exists?("/etc/slackware-version") ||
|
||||
!Dir.glob("/usr/lib/setup/Plamo-*").empty?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def self.nfs_check_command(env)
|
||||
"pidof nfsd > /dev/null"
|
||||
"/sbin/service nfsserver status"
|
||||
end
|
||||
|
||||
def self.nfs_start_command(env)
|
||||
|
|
|
@ -2,6 +2,8 @@ require "pathname"
|
|||
require "tempfile"
|
||||
|
||||
require "vagrant/util/downloader"
|
||||
require "vagrant/util/file_checksum"
|
||||
require "vagrant/util/powershell"
|
||||
require "vagrant/util/subprocess"
|
||||
|
||||
module VagrantPlugins
|
||||
|
@ -10,8 +12,9 @@ module VagrantPlugins
|
|||
class ProviderInstallVirtualBox
|
||||
# The URL to download VirtualBox is hardcoded so we can have a
|
||||
# known-good version to download.
|
||||
URL = "http://download.virtualbox.org/virtualbox/5.0.8/VirtualBox-5.0.8-103449-Win.exe".freeze
|
||||
VERSION = "5.0.8".freeze
|
||||
URL = "http://download.virtualbox.org/virtualbox/5.0.10/VirtualBox-5.0.10-104061-Win.exe".freeze
|
||||
VERSION = "5.0.10".freeze
|
||||
SHA256SUM = "3e5ed8fe4ada6eef8dfb4fe6fd79fcab4b242acf799f7d3ab4a17b43838b1e04".freeze
|
||||
|
||||
def self.provider_install_virtualbox(env)
|
||||
tf = Tempfile.new("vagrant")
|
||||
|
@ -29,13 +32,22 @@ module VagrantPlugins
|
|||
dl = Vagrant::Util::Downloader.new(URL, tf.path, ui: ui)
|
||||
dl.download!
|
||||
|
||||
# Validate that the file checksum matches
|
||||
actual = Vagrant::Util::FileChecksum.new(tf.path, Digest::SHA2).checksum
|
||||
if actual != SHA256SUM
|
||||
raise Vagrant::Errors::ProviderChecksumMismatch,
|
||||
provider: "virtualbox",
|
||||
actual: actual,
|
||||
expected: SHA256SUM
|
||||
end
|
||||
|
||||
# Launch it
|
||||
ui.output(I18n.t(
|
||||
"vagrant.hosts.windows.virtualbox_install_install"))
|
||||
ui.detail(I18n.t(
|
||||
"vagrant.hosts.windows.virtualbox_install_install_detail"))
|
||||
script = File.expand_path("../../scripts/install_virtualbox.ps1", __FILE__)
|
||||
result = Vagrant::Util::Powershell.execute(script, tf.path)
|
||||
result = Vagrant::Util::PowerShell.execute(script, tf.path)
|
||||
if result.exit_code != 0
|
||||
raise Vagrant::Errors::ProviderInstallFailed,
|
||||
provider: "virtualbox",
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
require "pathname"
|
||||
require "tmpdir"
|
||||
|
||||
require "vagrant/util/subprocess"
|
||||
|
||||
module VagrantPlugins
|
||||
module HostWindows
|
||||
module Cap
|
||||
class PS
|
||||
def self.ps_client(env, ps_info)
|
||||
logger = Log4r::Logger.new("vagrant::hosts::windows")
|
||||
|
||||
command = <<-EOS
|
||||
$plain_password = "#{ps_info[:password]}"
|
||||
$username = "#{ps_info[:username]}"
|
||||
$port = "#{ps_info[:port]}"
|
||||
$hostname = "#{ps_info[:host]}"
|
||||
$password = ConvertTo-SecureString $plain_password -asplaintext -force
|
||||
$creds = New-Object System.Management.Automation.PSCredential ("$hostname\\$username", $password)
|
||||
function prompt { kill $PID }
|
||||
Enter-PSSession -ComputerName $hostname -Credential $creds -Port $port
|
||||
EOS
|
||||
|
||||
logger.debug("Starting remote powershell with command:\n#{command}")
|
||||
|
||||
args = ["-NoProfile"]
|
||||
args << "-ExecutionPolicy"
|
||||
args << "Bypass"
|
||||
args << "-NoExit"
|
||||
args << "-EncodedCommand"
|
||||
args << ::WinRM::PowershellScript.new(command).encoded
|
||||
if ps_info[:extra_args]
|
||||
args << ps_info[:extra_args]
|
||||
end
|
||||
|
||||
# Launch it
|
||||
Vagrant::Util::Subprocess.execute("powershell", *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -25,6 +25,11 @@ module VagrantPlugins
|
|||
require_relative "cap/rdp"
|
||||
Cap::RDP
|
||||
end
|
||||
|
||||
host_capability("windows", "ps_client") do
|
||||
require_relative "cap/ps"
|
||||
Cap::PS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,7 @@ module VagrantPlugins
|
|||
attr_accessor :private_key_path
|
||||
attr_accessor :forward_agent
|
||||
attr_accessor :forward_x11
|
||||
attr_accessor :forward_env
|
||||
attr_accessor :shell
|
||||
|
||||
def initialize
|
||||
|
@ -26,6 +27,7 @@ module VagrantPlugins
|
|||
@private_key_path = UNSET_VALUE
|
||||
@forward_agent = UNSET_VALUE
|
||||
@forward_x11 = UNSET_VALUE
|
||||
@forward_env = UNSET_VALUE
|
||||
@shell = UNSET_VALUE
|
||||
end
|
||||
|
||||
|
@ -37,6 +39,7 @@ module VagrantPlugins
|
|||
new.ssh.private_key_path = @private_key_path if @private_key_path != UNSET_VALUE
|
||||
new.ssh.forward_agent = @forward_agent if @forward_agent != UNSET_VALUE
|
||||
new.ssh.forward_x11 = @forward_x11 if @forward_x11 != UNSET_VALUE
|
||||
new.ssh.forward_env = @forward_env if @forward_env != UNSET_VALUE
|
||||
new.ssh.shell = @shell if @shell != UNSET_VALUE
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ module VagrantPlugins
|
|||
class SSHConfig < SSHConnectConfig
|
||||
attr_accessor :forward_agent
|
||||
attr_accessor :forward_x11
|
||||
attr_accessor :forward_env
|
||||
attr_accessor :guest_port
|
||||
attr_accessor :keep_alive
|
||||
attr_accessor :shell
|
||||
|
@ -22,6 +23,7 @@ module VagrantPlugins
|
|||
|
||||
@forward_agent = UNSET_VALUE
|
||||
@forward_x11 = UNSET_VALUE
|
||||
@forward_env = UNSET_VALUE
|
||||
@guest_port = UNSET_VALUE
|
||||
@keep_alive = UNSET_VALUE
|
||||
@proxy_command = UNSET_VALUE
|
||||
|
@ -45,6 +47,7 @@ module VagrantPlugins
|
|||
|
||||
@forward_agent = false if @forward_agent == UNSET_VALUE
|
||||
@forward_x11 = false if @forward_x11 == UNSET_VALUE
|
||||
@forward_env = false if @forward_env == UNSET_VALUE
|
||||
@guest_port = 22 if @guest_port == UNSET_VALUE
|
||||
@keep_alive = true if @keep_alive == UNSET_VALUE
|
||||
@proxy_command = nil if @proxy_command == UNSET_VALUE
|
||||
|
|
|
@ -416,7 +416,8 @@ module VagrantPlugins
|
|||
host_ip: "127.0.0.1",
|
||||
id: "winrm",
|
||||
auto_correct: true
|
||||
|
||||
end
|
||||
if !@__networks["forwarded_port-winrm-ssl"]
|
||||
network :forwarded_port,
|
||||
guest: 5986,
|
||||
host: 55986,
|
||||
|
@ -697,7 +698,7 @@ module VagrantPlugins
|
|||
end
|
||||
end
|
||||
|
||||
if options[:ip] && options[:ip].end_with?(".1")
|
||||
if options[:ip] && options[:ip].end_with?(".1") && options[:type].to_sym != :dhcp
|
||||
machine.ui.warn(I18n.t(
|
||||
"vagrant.config.vm.network_ip_ends_in_one"))
|
||||
end
|
||||
|
|
|
@ -156,12 +156,12 @@ module VagrantPlugins
|
|||
b3.use Call, DestroyConfirm do |env3, b4|
|
||||
if env3[:result]
|
||||
b4.use ConfigValidate
|
||||
b4.use ProvisionerCleanup, :before
|
||||
b4.use EnvSet, force_halt: true
|
||||
b4.use action_halt
|
||||
b4.use HostMachineSyncFoldersDisable
|
||||
b4.use Destroy
|
||||
b4.use DestroyBuildImage
|
||||
b4.use ProvisionerCleanup
|
||||
else
|
||||
b4.use Message,
|
||||
I18n.t("docker_provider.messages.will_not_destroy")
|
||||
|
|
|
@ -38,6 +38,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
b2.use ConfigValidate
|
||||
b2.use ProvisionerCleanup, :before
|
||||
b2.use StopInstance
|
||||
b2.use DeleteVM
|
||||
end
|
||||
|
|
|
@ -16,8 +16,9 @@ module VagrantPlugins
|
|||
raise Errors::WindowsRequired
|
||||
end
|
||||
|
||||
if !Vagrant::Util::Platform.windows_admin?
|
||||
raise Errors::AdminRequired
|
||||
if !Vagrant::Util::Platform.windows_admin? and
|
||||
!Vagrant::Util::Platform.windows_hyperv_admin?
|
||||
raise Errors::AdminRequired
|
||||
end
|
||||
|
||||
if !Vagrant::Util::PowerShell.available?
|
||||
|
|
|
@ -7,9 +7,19 @@ Param(
|
|||
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
||||
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
||||
|
||||
$ip_address = ""
|
||||
$vm = Get-VM -Id $VmId -ErrorAction "Stop"
|
||||
$network = Get-VMNetworkAdapter -VM $vm
|
||||
$ip_address = $network.IpAddresses[0]
|
||||
$networks = Get-VMNetworkAdapter -VM $vm
|
||||
foreach ($network in $networks) {
|
||||
if ($network.IpAddresses.Length -gt 0) {
|
||||
$ip_address = $network.IpAddresses[0]
|
||||
if (-Not ([string]::IsNullOrEmpty($ip_address))) {
|
||||
# We found our IP address!
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$resultHash = @{
|
||||
ip = "$ip_address"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ try {
|
|||
$VM = Get-VM -Id $VmId -ErrorAction "Stop"
|
||||
$State = $VM.state
|
||||
$Status = $VM.status
|
||||
} catch [Microsoft.HyperV.PowerShell.VirtualizationOperationFailedException] {
|
||||
} catch [Microsoft.HyperV.PowerShell.VirtualizationException] {
|
||||
$State = "not_created"
|
||||
$Status = $State
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue