merge with upstream master / fix conflickt in layout
This commit is contained in:
commit
b98db9ce59
|
@ -1,6 +1,10 @@
|
||||||
# OS-specific
|
# OS-specific
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Editor swapfiles
|
||||||
|
.*.sw?
|
||||||
|
*~
|
||||||
|
|
||||||
# Vagrant stuff
|
# Vagrant stuff
|
||||||
acceptance_config.yml
|
acceptance_config.yml
|
||||||
boxes/*
|
boxes/*
|
||||||
|
|
140
CHANGELOG.md
140
CHANGELOG.md
|
@ -2,22 +2,162 @@
|
||||||
|
|
||||||
FEATURES:
|
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**: VirtualBox and VMware providers now support
|
||||||
linked clones for very fast (millisecond) imports on up. [GH-4484]
|
linked clones for very fast (millisecond) imports on up. [GH-4484]
|
||||||
- **Snapshots**: The `vagrant snapshot` command can be used to checkpoint
|
- **Snapshots**: The `vagrant snapshot` command can be used to checkpoint
|
||||||
and restore point-in-time snapshots.
|
and restore point-in-time snapshots.
|
||||||
- **IPv6 Private Networks**: Private networking now supports IPv6. This
|
- **IPv6 Private Networks**: Private networking now supports IPv6. This
|
||||||
only works with VirtualBox and VMware at this point. [GH-6342]
|
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:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
- core: allow removal of all box versions with `--all` flag [GH-3462]
|
- 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:
|
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: 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`
|
- provisioners/ansible: use quotes for the `ansible_ssh_private_key_file`
|
||||||
value in the generated inventory [GH-6209]
|
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)
|
## 1.7.4 (July 17, 2015)
|
||||||
|
|
||||||
|
|
10
README.md
10
README.md
|
@ -1,6 +1,6 @@
|
||||||
# Vagrant
|
# 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)
|
* Source: [https://github.com/mitchellh/vagrant](https://github.com/mitchellh/vagrant)
|
||||||
* IRC: `#vagrant` on Freenode
|
* IRC: `#vagrant` on Freenode
|
||||||
* Mailing list: [Google Groups](http://groups.google.com/group/vagrant-up)
|
* Mailing list: [Google Groups](http://groups.google.com/group/vagrant-up)
|
||||||
|
@ -19,12 +19,12 @@ between Windows, Mac OS X, and Linux.
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
For the quick-start, we'll bring up a development machine on
|
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
|
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
|
First, make sure your development machine has
|
||||||
[VirtualBox](http://www.virtualbox.org)
|
[VirtualBox](https://www.virtualbox.org/)
|
||||||
installed. After this,
|
installed. After this,
|
||||||
[download and install the appropriate Vagrant package for your OS](http://www.vagrantup.com/downloads).
|
[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
|
### 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:
|
be installed with a simple `gem install bundler`. Afterwards, do the following:
|
||||||
|
|
||||||
bundle install
|
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`.
|
* `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
|
* `st` - Contains a `.sublime-settings` file for enabling Ruby syntax highlighting
|
||||||
for `Vagrantfile`s in Sublime Text.
|
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
|
* `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_CHECK = /usr/bin/systemctl status nfs-server.service
|
||||||
Cmnd_Alias VAGRANT_NFSD_START = /usr/bin/systemctl start 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_NFSD_APPLY = /usr/sbin/exportfs -ar
|
||||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports
|
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /*/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_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_CHECK = /etc/init.d/nfs-kernel-server status
|
||||||
Cmnd_Alias VAGRANT_NFSD_START = /etc/init.d/nfs-kernel-server start
|
Cmnd_Alias VAGRANT_NFSD_START = /etc/init.d/nfs-kernel-server start
|
||||||
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
|
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
|
||||||
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports
|
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /*/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_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.")
|
@logger.info("URL is a file or protocol not found and assuming file.")
|
||||||
file_path = File.expand_path(url)
|
file_path = File.expand_path(url)
|
||||||
file_path = Util::Platform.cygwin_windows_path(file_path)
|
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
|
end
|
||||||
|
|
||||||
# If the temporary path exists, verify it is not too old. If its
|
# If the temporary path exists, verify it is not too old. If its
|
||||||
|
@ -491,6 +493,12 @@ module Vagrant
|
||||||
end
|
end
|
||||||
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
|
output = d.head
|
||||||
match = output.scan(/^Content-Type: (.+?)$/i).last
|
match = output.scan(/^Content-Type: (.+?)$/i).last
|
||||||
return false if !match
|
return false if !match
|
||||||
|
@ -507,14 +515,14 @@ module Vagrant
|
||||||
Digest::SHA2
|
Digest::SHA2
|
||||||
else
|
else
|
||||||
raise Errors::BoxChecksumInvalidType,
|
raise Errors::BoxChecksumInvalidType,
|
||||||
type: env[:box_checksum_type].to_s
|
type: checksum_type.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
@logger.info("Validating checksum with #{checksum_klass}")
|
@logger.info("Validating checksum with #{checksum_klass}")
|
||||||
@logger.info("Expected checksum: #{checksum}")
|
@logger.info("Expected checksum: #{checksum}")
|
||||||
|
|
||||||
actual = FileChecksum.new(path, checksum_klass).checksum
|
actual = FileChecksum.new(path, checksum_klass).checksum
|
||||||
if actual != checksum
|
if actual.casecmp(checksum) != 0
|
||||||
raise Errors::BoxChecksumMismatch,
|
raise Errors::BoxChecksumMismatch,
|
||||||
actual: actual,
|
actual: actual,
|
||||||
expected: checksum
|
expected: checksum
|
||||||
|
|
|
@ -37,13 +37,23 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
constraints = machine.config.vm.box_version
|
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(
|
env[:ui].output(I18n.t(
|
||||||
"vagrant.box_outdated_checking_with_refresh",
|
"vagrant.box_outdated_checking_with_refresh",
|
||||||
name: box.name))
|
name: box.name))
|
||||||
update = nil
|
update = nil
|
||||||
begin
|
begin
|
||||||
update = box.has_update?(constraints)
|
update = box.has_update?(constraints, download_options: download_options)
|
||||||
rescue Errors::BoxMetadataDownloadError => e
|
rescue Errors::BoxMetadataDownloadError => e
|
||||||
env[:ui].warn(I18n.t(
|
env[:ui].warn(I18n.t(
|
||||||
"vagrant.box_outdated_metadata_download_error",
|
"vagrant.box_outdated_metadata_download_error",
|
||||||
|
|
|
@ -111,6 +111,7 @@ module Vagrant
|
||||||
provider: box.provider,
|
provider: box.provider,
|
||||||
version: box.version))
|
version: box.version))
|
||||||
box.destroy!
|
box.destroy!
|
||||||
|
env[:box_collection].clean(box.name)
|
||||||
|
|
||||||
# Passes on the removed box to the rest of the middleware chain
|
# Passes on the removed box to the rest of the middleware chain
|
||||||
env[:box_removed] = box
|
env[:box_removed] = box
|
||||||
|
|
|
@ -128,7 +128,7 @@ module Vagrant
|
||||||
port_checker[repaired_port] ||
|
port_checker[repaired_port] ||
|
||||||
lease_check(repaired_port)
|
lease_check(repaired_port)
|
||||||
if in_use
|
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
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -156,8 +156,6 @@ module Vagrant
|
||||||
new_port: repaired_port.to_s))
|
new_port: repaired_port.to_s))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@app.call(env)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def lease_check(port)
|
def lease_check(port)
|
||||||
|
|
|
@ -76,6 +76,16 @@ module Vagrant
|
||||||
if opts[:merge]
|
if opts[:merge]
|
||||||
existing = cached_synced_folders(machine)
|
existing = cached_synced_folders(machine)
|
||||||
if existing
|
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|
|
folders.each do |impl, fs|
|
||||||
existing[impl] ||= {}
|
existing[impl] ||= {}
|
||||||
fs.each do |id, data|
|
fs.each do |id, data|
|
||||||
|
@ -101,7 +111,12 @@ module Vagrant
|
||||||
return cached_synced_folders(machine) if opts[:cached]
|
return cached_synced_folders(machine) if opts[:cached]
|
||||||
|
|
||||||
config = opts[:config]
|
config = opts[:config]
|
||||||
config ||= machine.config.vm
|
root = false
|
||||||
|
if !config
|
||||||
|
config = machine.config.vm
|
||||||
|
root = true
|
||||||
|
end
|
||||||
|
|
||||||
config_folders = config.synced_folders
|
config_folders = config.synced_folders
|
||||||
folders = {}
|
folders = {}
|
||||||
|
|
||||||
|
@ -131,9 +146,17 @@ module Vagrant
|
||||||
end
|
end
|
||||||
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.
|
# Keep track of this shared folder by the implementation.
|
||||||
folders[impl] ||= {}
|
folders[impl] ||= {}
|
||||||
folders[impl][id] = data.dup
|
folders[impl][id] = data
|
||||||
end
|
end
|
||||||
|
|
||||||
# If we have folders with the "default" key, then determine the
|
# If we have folders with the "default" key, then determine the
|
||||||
|
|
|
@ -13,8 +13,9 @@ module Vagrant
|
||||||
def initialize(app, env, place=nil)
|
def initialize(app, env, place=nil)
|
||||||
@app = app
|
@app = app
|
||||||
@logger = Log4r::Logger.new("vagrant::action::builtin::provision_cleanup")
|
@logger = Log4r::Logger.new("vagrant::action::builtin::provision_cleanup")
|
||||||
@place ||= :after
|
|
||||||
@place = @place.to_sym
|
place ||= :after
|
||||||
|
@place = place.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
|
@ -31,10 +32,20 @@ module Vagrant
|
||||||
|
|
||||||
# Ask the provisioners to modify the configuration if needed
|
# Ask the provisioners to modify the configuration if needed
|
||||||
provisioner_instances(env).each do |p, _|
|
provisioner_instances(env).each do |p, _|
|
||||||
env[:ui].info(I18n.t(
|
name = type_map[p].to_s
|
||||||
"vagrant.provisioner_cleanup",
|
|
||||||
name: type_map[p].to_s))
|
# Check if the subclass defined a cleanup method. The parent
|
||||||
p.cleanup
|
# 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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,6 +23,7 @@ module Vagrant
|
||||||
config: env[:synced_folders_config],
|
config: env[:synced_folders_config],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@logger.info("SyncedFolders loading from cache: #{opts[:cached]}")
|
||||||
folders = synced_folders(env[:machine], **opts)
|
folders = synced_folders(env[:machine], **opts)
|
||||||
original_folders = folders
|
original_folders = folders
|
||||||
|
|
||||||
|
@ -121,8 +122,11 @@ module Vagrant
|
||||||
|
|
||||||
save_synced_folders(env[:machine], all)
|
save_synced_folders(env[:machine], all)
|
||||||
else
|
else
|
||||||
|
save_opts = { merge: true }
|
||||||
|
save_opts[:vagrantfile] = true if !opts[:config]
|
||||||
|
|
||||||
# Save the synced folders
|
# 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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,7 +30,7 @@ module Vagrant
|
||||||
def call(env)
|
def call(env)
|
||||||
@env = env
|
@env = env
|
||||||
file_name = File.basename(@env["package.output"].to_s)
|
file_name = File.basename(@env["package.output"].to_s)
|
||||||
|
|
||||||
raise Errors::PackageOutputDirectory if File.directory?(tar_path)
|
raise Errors::PackageOutputDirectory if File.directory?(tar_path)
|
||||||
raise Errors::PackageOutputExists, file_name:file_name if File.exist?(tar_path)
|
raise Errors::PackageOutputExists, file_name:file_name if File.exist?(tar_path)
|
||||||
raise Errors::PackageRequiresDirectory if !env["package.directory"] ||
|
raise Errors::PackageRequiresDirectory if !env["package.directory"] ||
|
||||||
|
@ -113,6 +113,21 @@ module Vagrant
|
||||||
|
|
||||||
# If we don't have a generated private key, we do nothing
|
# If we don't have a generated private key, we do nothing
|
||||||
path = @env[:machine].data_dir.join("private_key")
|
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?
|
return if !path.file?
|
||||||
|
|
||||||
# Copy it into our box directory
|
# Copy it into our box directory
|
||||||
|
|
|
@ -115,8 +115,9 @@ module Vagrant
|
||||||
# Loads the metadata URL and returns the latest metadata associated
|
# Loads the metadata URL and returns the latest metadata associated
|
||||||
# with this box.
|
# with this box.
|
||||||
#
|
#
|
||||||
|
# @param [Hash] download_options Options to pass to the downloader.
|
||||||
# @return [BoxMetadata]
|
# @return [BoxMetadata]
|
||||||
def load_metadata
|
def load_metadata(**download_options)
|
||||||
tf = Tempfile.new("vagrant")
|
tf = Tempfile.new("vagrant")
|
||||||
tf.close
|
tf.close
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ module Vagrant
|
||||||
url = "file:#{url}"
|
url = "file:#{url}"
|
||||||
end
|
end
|
||||||
|
|
||||||
opts = { headers: ["Accept: application/json"] }
|
opts = { headers: ["Accept: application/json"] }.merge(download_options)
|
||||||
Util::Downloader.new(url, tf.path, **opts).download!
|
Util::Downloader.new(url, tf.path, **opts).download!
|
||||||
BoxMetadata.new(File.open(tf.path, "r"))
|
BoxMetadata.new(File.open(tf.path, "r"))
|
||||||
rescue Errors::DownloaderError => e
|
rescue Errors::DownloaderError => e
|
||||||
|
@ -148,7 +149,7 @@ module Vagrant
|
||||||
# satisfy. If nil, the version constrain defaults to being a
|
# satisfy. If nil, the version constrain defaults to being a
|
||||||
# larger version than this box.
|
# larger version than this box.
|
||||||
# @return [Array]
|
# @return [Array]
|
||||||
def has_update?(version=nil)
|
def has_update?(version=nil, download_options: {})
|
||||||
if !@metadata_url
|
if !@metadata_url
|
||||||
raise Errors::BoxUpdateNoMetadata, name: @name
|
raise Errors::BoxUpdateNoMetadata, name: @name
|
||||||
end
|
end
|
||||||
|
@ -156,7 +157,7 @@ module Vagrant
|
||||||
version += ", " if version
|
version += ", " if version
|
||||||
version ||= ""
|
version ||= ""
|
||||||
version += "> #{@version}"
|
version += "> #{@version}"
|
||||||
md = self.load_metadata
|
md = self.load_metadata(download_options)
|
||||||
newer = md.version(version, provider: @provider)
|
newer = md.version(version, provider: @provider)
|
||||||
return nil if !newer
|
return nil if !newer
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,9 @@ module Vagrant
|
||||||
# for accessing/finding individual boxes, adding new boxes, or deleting
|
# for accessing/finding individual boxes, adding new boxes, or deleting
|
||||||
# boxes.
|
# boxes.
|
||||||
class BoxCollection
|
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.
|
# The directory where the boxes in this collection are stored.
|
||||||
#
|
#
|
||||||
|
@ -346,6 +348,14 @@ module Vagrant
|
||||||
end
|
end
|
||||||
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
|
protected
|
||||||
|
|
||||||
# Returns the directory name for the box of the given name.
|
# Returns the directory name for the box of the given name.
|
||||||
|
@ -354,16 +364,16 @@ module Vagrant
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def dir_name(name)
|
def dir_name(name)
|
||||||
name = name.dup
|
name = name.dup
|
||||||
name.gsub!(":", "-VAGRANTCOLON-") if Util::Platform.windows?
|
name.gsub!(":", VAGRANT_COLON) if Util::Platform.windows?
|
||||||
name.gsub!("/", "-VAGRANTSLASH-")
|
name.gsub!("/", VAGRANT_SLASH)
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the directory name for the box cleaned up
|
# Returns the directory name for the box cleaned up
|
||||||
def undir_name(name)
|
def undir_name(name)
|
||||||
name = name.dup
|
name = name.dup
|
||||||
name.gsub!("-VAGRANTCOLON-", ":")
|
name.gsub!(VAGRANT_COLON, ":")
|
||||||
name.gsub!("-VAGRANTSLASH-", "/")
|
name.gsub!(VAGRANT_SLASH, "/")
|
||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -440,5 +450,10 @@ module Vagrant
|
||||||
ensure
|
ensure
|
||||||
dir.rmtree if dir.exist?
|
dir.rmtree if dir.exist?
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ require "bundler"
|
||||||
|
|
||||||
require_relative "shared_helpers"
|
require_relative "shared_helpers"
|
||||||
require_relative "version"
|
require_relative "version"
|
||||||
|
require_relative "util/safe_env"
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
# This class manages Vagrant's interaction with Bundler. Vagrant uses
|
# This class manages Vagrant's interaction with Bundler. Vagrant uses
|
||||||
|
@ -42,6 +43,9 @@ module Vagrant
|
||||||
yield
|
yield
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Configure Bundler to retry
|
||||||
|
::Bundler.settings[:retry] = 3
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initializes Bundler and the various gem paths so that we can begin
|
# Initializes Bundler and the various gem paths so that we can begin
|
||||||
|
@ -68,12 +72,15 @@ module Vagrant
|
||||||
# we add all our plugin dependencies.
|
# we add all our plugin dependencies.
|
||||||
@gemfile = build_gemfile(plugins)
|
@gemfile = build_gemfile(plugins)
|
||||||
|
|
||||||
# Set the environmental variables for Bundler
|
Util::SafeEnv.change_env do |env|
|
||||||
ENV["BUNDLE_APP_CONFIG"] = @appconfigpath
|
# Set the environmental variables for Bundler
|
||||||
ENV["BUNDLE_CONFIG"] = @configfile.path
|
env["BUNDLE_APP_CONFIG"] = @appconfigpath
|
||||||
ENV["BUNDLE_GEMFILE"] = @gemfile.path
|
env["BUNDLE_CONFIG"] = @configfile.path
|
||||||
ENV["GEM_PATH"] =
|
env["BUNDLE_GEMFILE"] = @gemfile.path
|
||||||
"#{bundle_path}#{::File::PATH_SEPARATOR}#{@gem_path}"
|
env["GEM_PATH"] =
|
||||||
|
"#{bundle_path}#{::File::PATH_SEPARATOR}#{@gem_path}"
|
||||||
|
end
|
||||||
|
|
||||||
Gem.clear_paths
|
Gem.clear_paths
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -178,11 +185,6 @@ module Vagrant
|
||||||
|
|
||||||
f = File.open(Tempfile.new("vagrant").path + "2", "w+")
|
f = File.open(Tempfile.new("vagrant").path + "2", "w+")
|
||||||
f.tap do |gemfile|
|
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|
|
sources.each do |source|
|
||||||
next if source == ""
|
next if source == ""
|
||||||
gemfile.puts(%Q[source "#{source}"])
|
gemfile.puts(%Q[source "#{source}"])
|
||||||
|
|
|
@ -221,7 +221,12 @@ module Vagrant
|
||||||
|
|
||||||
line = "(unknown)"
|
line = "(unknown)"
|
||||||
if e.backtrace && e.backtrace[0]
|
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
|
end
|
||||||
|
|
||||||
# Report the generic exception
|
# Report the generic exception
|
||||||
|
|
|
@ -832,7 +832,7 @@ module Vagrant
|
||||||
|
|
||||||
# This creates the local data directory and show an error if it
|
# This creates the local data directory and show an error if it
|
||||||
# couldn't properly be created.
|
# couldn't properly be created.
|
||||||
def setup_local_data_path
|
def setup_local_data_path(force=false)
|
||||||
if @local_data_path.nil?
|
if @local_data_path.nil?
|
||||||
@logger.warn("No local data path is set. Local data cannot be stored.")
|
@logger.warn("No local data path is set. Local data cannot be stored.")
|
||||||
return
|
return
|
||||||
|
@ -847,6 +847,9 @@ module Vagrant
|
||||||
upgrade_v1_dotfile(@local_data_path)
|
upgrade_v1_dotfile(@local_data_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# If we don't have a root path, we don't setup anything
|
||||||
|
return if !force && root_path.nil?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@logger.debug("Creating: #{@local_data_path}")
|
@logger.debug("Creating: #{@local_data_path}")
|
||||||
FileUtils.mkdir_p(@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
|
# Now, we create the actual local data directory. This should succeed
|
||||||
# this time since we renamed the old conflicting V1.
|
# this time since we renamed the old conflicting V1.
|
||||||
setup_local_data_path
|
setup_local_data_path(true)
|
||||||
|
|
||||||
if json_data["active"]
|
if json_data["active"]
|
||||||
@logger.debug("Upgrading to V2 style for each active VM")
|
@logger.debug("Upgrading to V2 style for each active VM")
|
||||||
|
|
|
@ -108,14 +108,6 @@ module Vagrant
|
||||||
error_key(:active_machine_with_different_provider)
|
error_key(:active_machine_with_different_provider)
|
||||||
end
|
end
|
||||||
|
|
||||||
class AnsibleFailed < VagrantError
|
|
||||||
error_key(:ansible_failed)
|
|
||||||
end
|
|
||||||
|
|
||||||
class AnsiblePlaybookAppNotFound < VagrantError
|
|
||||||
error_key(:ansible_playbook_app_not_found)
|
|
||||||
end
|
|
||||||
|
|
||||||
class BatchMultiError < VagrantError
|
class BatchMultiError < VagrantError
|
||||||
error_key(:batch_multi_error)
|
error_key(:batch_multi_error)
|
||||||
end
|
end
|
||||||
|
@ -248,6 +240,10 @@ module Vagrant
|
||||||
error_key(:bundler_error)
|
error_key(:bundler_error)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class CantReadMACAddresses < VagrantError
|
||||||
|
error_key(:cant_read_mac_addresses)
|
||||||
|
end
|
||||||
|
|
||||||
class CapabilityHostExplicitNotDetected < VagrantError
|
class CapabilityHostExplicitNotDetected < VagrantError
|
||||||
error_key(:capability_host_explicit_not_detected)
|
error_key(:capability_host_explicit_not_detected)
|
||||||
end
|
end
|
||||||
|
@ -348,6 +344,10 @@ module Vagrant
|
||||||
error_key(:downloader_interrupted)
|
error_key(:downloader_interrupted)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class EnvInval < VagrantError
|
||||||
|
error_key(:env_inval)
|
||||||
|
end
|
||||||
|
|
||||||
class EnvironmentNonExistentCWD < VagrantError
|
class EnvironmentNonExistentCWD < VagrantError
|
||||||
error_key(:environment_non_existent_cwd)
|
error_key(:environment_non_existent_cwd)
|
||||||
end
|
end
|
||||||
|
@ -408,8 +408,8 @@ module Vagrant
|
||||||
error_key(:linux_nfs_mount_failed)
|
error_key(:linux_nfs_mount_failed)
|
||||||
end
|
end
|
||||||
|
|
||||||
class LinuxRDesktopNotFound < VagrantError
|
class LinuxRDPClientNotFound < VagrantError
|
||||||
error_key(:linux_rdesktop_not_found)
|
error_key(:linux_rdp_client_not_found)
|
||||||
end
|
end
|
||||||
|
|
||||||
class LocalDataDirectoryNotAccessible < VagrantError
|
class LocalDataDirectoryNotAccessible < VagrantError
|
||||||
|
@ -524,6 +524,10 @@ module Vagrant
|
||||||
error_key(:provider_cant_install)
|
error_key(:provider_cant_install)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ProviderChecksumMismatch < VagrantError
|
||||||
|
error_key(:provider_checksum_mismatch)
|
||||||
|
end
|
||||||
|
|
||||||
class ProviderInstallFailed < VagrantError
|
class ProviderInstallFailed < VagrantError
|
||||||
error_key(:provider_install_failed)
|
error_key(:provider_install_failed)
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,6 +116,9 @@ module Vagrant
|
||||||
# XXX: This is temporary. This will be removed very soon.
|
# XXX: This is temporary. This will be removed very soon.
|
||||||
if base
|
if base
|
||||||
@id = name
|
@id = name
|
||||||
|
|
||||||
|
# For base setups, we don't want to insert the key
|
||||||
|
@config.ssh.insert_key = false
|
||||||
else
|
else
|
||||||
reload
|
reload
|
||||||
end
|
end
|
||||||
|
@ -141,6 +144,10 @@ module Vagrant
|
||||||
if state.id == MachineState::NOT_CREATED_ID
|
if state.id == MachineState::NOT_CREATED_ID
|
||||||
self.id = nil
|
self.id = nil
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
# This calls an action on the provider. The provider may or may not
|
# This calls an action on the provider. The provider may or may not
|
||||||
|
@ -188,7 +195,10 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
# Call the action
|
# 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
|
end
|
||||||
rescue Errors::EnvironmentLockedError
|
rescue Errors::EnvironmentLockedError
|
||||||
raise Errors::MachineActionLockedError,
|
raise Errors::MachineActionLockedError,
|
||||||
|
@ -436,6 +446,7 @@ module Vagrant
|
||||||
# We also set some fields that are purely controlled by Varant
|
# We also set some fields that are purely controlled by Varant
|
||||||
info[:forward_agent] = @config.ssh.forward_agent
|
info[:forward_agent] = @config.ssh.forward_agent
|
||||||
info[:forward_x11] = @config.ssh.forward_x11
|
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
|
info[:ssh_command] = @config.ssh.ssh_command if @config.ssh.ssh_command
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ module Vagrant
|
||||||
@machines.delete(entry.id)
|
@machines.delete(entry.id)
|
||||||
unlocked_save
|
unlocked_save
|
||||||
|
|
||||||
# Release acccess on this machine
|
# Release access on this machine
|
||||||
unlocked_release(entry.id)
|
unlocked_release(entry.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -133,8 +133,17 @@ module Vagrant
|
||||||
# machine in that environment. We silence warnings here because
|
# machine in that environment. We silence warnings here because
|
||||||
# Vagrantfiles often have constants, so people would otherwise
|
# Vagrantfiles often have constants, so people would otherwise
|
||||||
# constantly (heh) get "already initialized constant" warnings.
|
# constantly (heh) get "already initialized constant" warnings.
|
||||||
env = entry.vagrant_env(
|
begin
|
||||||
@env.home_path, ui_class: @env.ui_class)
|
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)
|
next env.machine(entry.name.to_sym, entry.provider.to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -104,8 +104,8 @@ module Vagrant
|
||||||
end
|
end
|
||||||
|
|
||||||
[:detail, :warn, :error, :info, :output, :success].each do |method|
|
[:detail, :warn, :error, :info, :output, :success].each do |method|
|
||||||
define_method(method) do |message, *opts|
|
define_method(method) do |message, *args, **opts|
|
||||||
machine("ui", method.to_s, message)
|
machine("ui", method.to_s, message, *args, **opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,9 +123,12 @@ module Vagrant
|
||||||
data[i].gsub!("\r", "\\r")
|
data[i].gsub!("\r", "\\r")
|
||||||
end
|
end
|
||||||
|
|
||||||
@lock.synchronize do
|
# Avoid locks in a trap context introduced from Ruby 2.0
|
||||||
safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
|
Thread.new do
|
||||||
end
|
@lock.synchronize do
|
||||||
|
safe_puts("#{Time.now.utc.to_i},#{target},#{type},#{data.join(",")}")
|
||||||
|
end
|
||||||
|
end.join
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -156,7 +159,7 @@ module Vagrant
|
||||||
super(message)
|
super(message)
|
||||||
|
|
||||||
# We can't ask questions when the output isn't a TTY.
|
# We can't ask questions when the output isn't a TTY.
|
||||||
raise Errors::UIExpectsTTY if !@stdin.tty? && !Vagrant::Util::Platform.cygwin?
|
raise Errors::UIExpectsTTY if !@stdin.tty? && !Vagrant::Util::Platform.windows?
|
||||||
|
|
||||||
# Setup the options so that the new line is suppressed
|
# Setup the options so that the new line is suppressed
|
||||||
opts ||= {}
|
opts ||= {}
|
||||||
|
@ -277,6 +280,9 @@ module Vagrant
|
||||||
opts[:bold] = #{method.inspect} != :detail && \
|
opts[:bold] = #{method.inspect} != :detail && \
|
||||||
#{method.inspect} != :ask
|
#{method.inspect} != :ask
|
||||||
end
|
end
|
||||||
|
if !opts.key?(:target)
|
||||||
|
opts[:target] = @prefix
|
||||||
|
end
|
||||||
@ui.#{method}(format_message(#{method.inspect}, message, **opts), *args, **opts)
|
@ui.#{method}(format_message(#{method.inspect}, message, **opts), *args, **opts)
|
||||||
end
|
end
|
||||||
CODE
|
CODE
|
||||||
|
|
|
@ -138,11 +138,14 @@ module Vagrant
|
||||||
# If we already retried, raise it.
|
# If we already retried, raise it.
|
||||||
raise if retried
|
raise if retried
|
||||||
|
|
||||||
|
@logger.error("Exit code: #{e.extra_data[:code]}")
|
||||||
|
|
||||||
# If its any error other than 33, it is an error.
|
# 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.
|
# Exit code 33 means that the server doesn't support ranges.
|
||||||
# In this case, try again without resume.
|
# In this case, try again without resume.
|
||||||
|
@logger.error("Error is server doesn't support byte ranges. Retrying from scratch.")
|
||||||
@continue = false
|
@continue = false
|
||||||
retried = true
|
retried = true
|
||||||
retry
|
retry
|
||||||
|
|
|
@ -10,10 +10,17 @@ module Vagrant
|
||||||
class Platform
|
class Platform
|
||||||
class << self
|
class << self
|
||||||
def cygwin?
|
def cygwin?
|
||||||
|
# Installer detects Cygwin
|
||||||
return true if ENV["VAGRANT_DETECTED_OS"] &&
|
return true if ENV["VAGRANT_DETECTED_OS"] &&
|
||||||
ENV["VAGRANT_DETECTED_OS"].downcase.include?("cygwin")
|
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
|
end
|
||||||
|
|
||||||
[:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
|
[:darwin, :bsd, :freebsd, :linux, :solaris].each do |type|
|
||||||
|
@ -45,10 +52,32 @@ module Vagrant
|
||||||
# detect-if-running-with-administrator-privileges-under-windows-xp
|
# detect-if-running-with-administrator-privileges-under-windows-xp
|
||||||
begin
|
begin
|
||||||
Win32::Registry::HKEY_USERS.open("S-1-5-19") {}
|
Win32::Registry::HKEY_USERS.open("S-1-5-19") {}
|
||||||
return true
|
|
||||||
rescue Win32::Registry::Error
|
rescue Win32::Registry::Error
|
||||||
return false
|
return false
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
# This takes any path and converts it from a Windows path to a
|
# 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))
|
path = Pathname.new(File.expand_path(path))
|
||||||
|
|
||||||
if path.exist? && !fs_case_sensitive?
|
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
|
# Build up all the parts of the path
|
||||||
original = []
|
original = []
|
||||||
while !path.root?
|
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]}"]
|
command_options += ["-o", "ProxyCommand=#{ssh_info[:proxy_command]}"]
|
||||||
end
|
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
|
# 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,
|
# 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
|
# 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}")
|
LOGGER.info("Executing SSH in subprocess: #{ssh} #{command_options.inspect}")
|
||||||
process = ChildProcess.build(ssh, *command_options)
|
process = ChildProcess.build(ssh, *command_options)
|
||||||
process.io.inherit!
|
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.start
|
||||||
process.wait
|
process.wait
|
||||||
return process.exit_code
|
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 'optparse'
|
||||||
|
|
||||||
|
require_relative 'download_mixins'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module CommandBox
|
module CommandBox
|
||||||
module Command
|
module Command
|
||||||
class Add < Vagrant.plugin("2", :command)
|
class Add < Vagrant.plugin("2", :command)
|
||||||
|
include DownloadMixins
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
options = {}
|
options = {}
|
||||||
|
|
||||||
|
@ -21,22 +25,7 @@ module VagrantPlugins
|
||||||
options[:force] = f
|
options[:force] = f
|
||||||
end
|
end
|
||||||
|
|
||||||
o.on("--insecure", "Do not validate SSL certificates") do |i|
|
build_download_options(o, options)
|
||||||
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
|
|
||||||
|
|
||||||
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|
|
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
|
options[:location_trusted] = l
|
||||||
|
@ -97,7 +86,7 @@ module VagrantPlugins
|
||||||
box_force: options[:force],
|
box_force: options[:force],
|
||||||
box_download_ca_cert: options[:ca_cert],
|
box_download_ca_cert: options[:ca_cert],
|
||||||
box_download_ca_path: options[:ca_path],
|
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_insecure: options[:insecure],
|
||||||
box_download_location_trusted: options[:location_trusted],
|
box_download_location_trusted: options[:location_trusted],
|
||||||
ui: Vagrant::UI::Prefixed.new(@env.ui, "box"),
|
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 'optparse'
|
||||||
|
|
||||||
|
require_relative 'download_mixins'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module CommandBox
|
module CommandBox
|
||||||
module Command
|
module Command
|
||||||
class Outdated < Vagrant.plugin("2", :command)
|
class Outdated < Vagrant.plugin("2", :command)
|
||||||
|
include DownloadMixins
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
options = {}
|
options = {}
|
||||||
|
download_options = {}
|
||||||
|
|
||||||
opts = OptionParser.new do |o|
|
opts = OptionParser.new do |o|
|
||||||
o.banner = "Usage: vagrant box outdated [options]"
|
o.banner = "Usage: vagrant box outdated [options]"
|
||||||
|
@ -20,6 +25,8 @@ module VagrantPlugins
|
||||||
o.on("--global", "Check all boxes installed") do |g|
|
o.on("--global", "Check all boxes installed") do |g|
|
||||||
options[:global] = g
|
options[:global] = g
|
||||||
end
|
end
|
||||||
|
|
||||||
|
build_download_options(o, download_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
argv = parse_options(opts)
|
argv = parse_options(opts)
|
||||||
|
@ -27,7 +34,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
# If we're checking the boxes globally, then do that.
|
# If we're checking the boxes globally, then do that.
|
||||||
if options[:global]
|
if options[:global]
|
||||||
outdated_global
|
outdated_global(download_options)
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,11 +44,11 @@ module VagrantPlugins
|
||||||
box_outdated_refresh: true,
|
box_outdated_refresh: true,
|
||||||
box_outdated_success_ui: true,
|
box_outdated_success_ui: true,
|
||||||
machine: machine,
|
machine: machine,
|
||||||
})
|
}.merge(download_options))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def outdated_global
|
def outdated_global(download_options)
|
||||||
boxes = {}
|
boxes = {}
|
||||||
@env.boxes.all.reverse.each do |name, version, provider|
|
@env.boxes.all.reverse.each do |name, version, provider|
|
||||||
next if boxes[name]
|
next if boxes[name]
|
||||||
|
@ -58,8 +65,8 @@ module VagrantPlugins
|
||||||
|
|
||||||
md = nil
|
md = nil
|
||||||
begin
|
begin
|
||||||
md = box.load_metadata
|
md = box.load_metadata(download_options)
|
||||||
rescue Vagrant::Errors::DownloaderError => e
|
rescue Vagrant::Errors::BoxMetadataDownloadError => e
|
||||||
@env.ui.error(I18n.t(
|
@env.ui.error(I18n.t(
|
||||||
"vagrant.box_outdated_metadata_error",
|
"vagrant.box_outdated_metadata_error",
|
||||||
name: box.name,
|
name: box.name,
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
|
|
||||||
|
require_relative 'download_mixins'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module CommandBox
|
module CommandBox
|
||||||
module Command
|
module Command
|
||||||
class Update < Vagrant.plugin("2", :command)
|
class Update < Vagrant.plugin("2", :command)
|
||||||
|
include DownloadMixins
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
options = {}
|
options = {}
|
||||||
|
download_options = {}
|
||||||
|
|
||||||
opts = OptionParser.new do |o|
|
opts = OptionParser.new do |o|
|
||||||
o.banner = "Usage: vagrant box update [options]"
|
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|
|
o.on("--provider PROVIDER", String, "Update box with specific provider") do |p|
|
||||||
options[:provider] = p.to_sym
|
options[:provider] = p.to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
|
build_download_options(o, download_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
argv = parse_options(opts)
|
argv = parse_options(opts)
|
||||||
return if !argv
|
return if !argv
|
||||||
|
|
||||||
if options[:box]
|
if options[:box]
|
||||||
update_specific(options[:box], options[:provider])
|
update_specific(options[:box], options[:provider], download_options)
|
||||||
else
|
else
|
||||||
update_vms(argv, options[:provider])
|
update_vms(argv, options[:provider], download_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_specific(name, provider)
|
def update_specific(name, provider, download_options)
|
||||||
boxes = {}
|
boxes = {}
|
||||||
@env.boxes.all.each do |n, v, p|
|
@env.boxes.all.each do |n, v, p|
|
||||||
boxes[n] ||= {}
|
boxes[n] ||= {}
|
||||||
|
@ -74,11 +81,11 @@ module VagrantPlugins
|
||||||
|
|
||||||
to_update.each do |n, p, v|
|
to_update.each do |n, p, v|
|
||||||
box = @env.boxes.find(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
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_vms(argv, provider)
|
def update_vms(argv, provider, download_options)
|
||||||
with_target_vms(argv, provider: provider) do |machine|
|
with_target_vms(argv, provider: provider) do |machine|
|
||||||
if !machine.config.vm.box
|
if !machine.config.vm.box
|
||||||
machine.ui.output(I18n.t(
|
machine.ui.output(I18n.t(
|
||||||
|
@ -95,17 +102,25 @@ module VagrantPlugins
|
||||||
|
|
||||||
box = machine.box
|
box = machine.box
|
||||||
version = machine.config.vm.box_version
|
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
|
||||||
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.output(I18n.t("vagrant.box_update_checking", name: box.name))
|
||||||
ui.detail("Latest installed version: #{box.version}")
|
ui.detail("Latest installed version: #{box.version}")
|
||||||
ui.detail("Version constraints: #{version}")
|
ui.detail("Version constraints: #{version}")
|
||||||
ui.detail("Provider: #{box.provider}")
|
ui.detail("Provider: #{box.provider}")
|
||||||
|
|
||||||
update = box.has_update?(version)
|
update = box.has_update?(version, download_options: download_options)
|
||||||
if !update
|
if !update
|
||||||
ui.success(I18n.t(
|
ui.success(I18n.t(
|
||||||
"vagrant.box_up_to_date_single",
|
"vagrant.box_up_to_date_single",
|
||||||
|
@ -124,6 +139,10 @@ module VagrantPlugins
|
||||||
box_provider: update[2].name,
|
box_provider: update[2].name,
|
||||||
box_version: update[1].version,
|
box_version: update[1].version,
|
||||||
ui: ui,
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
require "rest_client"
|
require "rest_client"
|
||||||
|
require "vagrant/util/downloader"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module LoginCommand
|
module LoginCommand
|
||||||
|
@ -45,8 +46,23 @@ module VagrantPlugins
|
||||||
with_error_handling do
|
with_error_handling do
|
||||||
url = "#{Vagrant.server_url}/api/v1/authenticate"
|
url = "#{Vagrant.server_url}/api/v1/authenticate"
|
||||||
request = { "user" => { "login" => user, "password" => pass } }
|
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 = JSON.load(response.to_s)
|
||||||
data["token"]
|
data["token"]
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
require "cgi"
|
||||||
require "uri"
|
require "uri"
|
||||||
|
|
||||||
require_relative "../client"
|
require_relative "../client"
|
||||||
|
@ -5,6 +6,9 @@ require_relative "../client"
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module LoginCommand
|
module LoginCommand
|
||||||
class AddAuthentication
|
class AddAuthentication
|
||||||
|
VCLOUD = "vagrantcloud.com".freeze
|
||||||
|
ATLAS = "atlas.hashicorp.com".freeze
|
||||||
|
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
@app = app
|
@app = app
|
||||||
end
|
end
|
||||||
|
@ -19,19 +23,26 @@ module VagrantPlugins
|
||||||
env[:box_urls].map! do |url|
|
env[:box_urls].map! do |url|
|
||||||
u = URI.parse(url)
|
u = URI.parse(url)
|
||||||
replace = u.host == server_uri.host
|
replace = u.host == server_uri.host
|
||||||
|
|
||||||
if !replace
|
if !replace
|
||||||
# We need this in here for the transition we made from
|
# We need this in here for the transition we made from
|
||||||
# Vagrant Cloud to Atlas. This preserves access tokens
|
# Vagrant Cloud to Atlas. This preserves access tokens
|
||||||
# appending to both without leaking access tokens to
|
# appending to both without leaking access tokens to
|
||||||
# unsavory URLs.
|
# unsavory URLs.
|
||||||
replace = u.host == "vagrantcloud.com" &&
|
if u.host == VCLOUD && server_uri.host == ATLAS
|
||||||
server_uri.host == "atlas.hashicorp.com"
|
replace = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if replace
|
if replace
|
||||||
u.query ||= ""
|
q = CGI.parse(u.query || "")
|
||||||
u.query += "&" if u.query != ""
|
|
||||||
u.query += "access_token=#{token}"
|
current = q["access_token"]
|
||||||
|
if current && current.empty?
|
||||||
|
q["access_token"] = token
|
||||||
|
end
|
||||||
|
|
||||||
|
u.query = URI.encode_www_form(q)
|
||||||
end
|
end
|
||||||
|
|
||||||
u.to_s
|
u.to_s
|
||||||
|
|
|
@ -3,6 +3,11 @@ module VagrantPlugins
|
||||||
module Command
|
module Command
|
||||||
module MixinInstallOpts
|
module MixinInstallOpts
|
||||||
def build_install_opts(o, options)
|
def build_install_opts(o, options)
|
||||||
|
options[:plugin_sources] = [
|
||||||
|
"https://rubygems.org",
|
||||||
|
"http://gems.hashicorp.com",
|
||||||
|
]
|
||||||
|
|
||||||
o.on("--entry-point NAME", String,
|
o.on("--entry-point NAME", String,
|
||||||
"The name of the entry point file for loading the plugin.") do |entry_point|
|
"The name of the entry point file for loading the plugin.") do |entry_point|
|
||||||
options[:entry_point] = entry_point
|
options[:entry_point] = entry_point
|
||||||
|
@ -17,9 +22,13 @@ module VagrantPlugins
|
||||||
puts
|
puts
|
||||||
end
|
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,
|
o.on("--plugin-source PLUGIN_SOURCE", String,
|
||||||
"Add a RubyGems repository source") do |plugin_source|
|
"Add a RubyGems repository source") do |plugin_source|
|
||||||
options[:plugin_sources] ||= []
|
|
||||||
options[:plugin_sources] << plugin_source
|
options[:plugin_sources] << plugin_source
|
||||||
end
|
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.banner = "Usage: vagrant provision [vm-name] [--provision-with x,y,z]"
|
||||||
|
|
||||||
o.on("--provision-with x,y,z", Array,
|
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 }
|
options[:provision_types] = list.map { |type| type.to_sym }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,7 +30,7 @@ module VagrantPlugins
|
||||||
return if !argv
|
return if !argv
|
||||||
|
|
||||||
# Validate the provisioners
|
# Validate the provisioners
|
||||||
validate_provisioner_flags!(options)
|
validate_provisioner_flags!(options, argv)
|
||||||
|
|
||||||
@logger.debug("'reload' each target VM...")
|
@logger.debug("'reload' each target VM...")
|
||||||
machines = []
|
machines = []
|
||||||
|
|
|
@ -41,12 +41,15 @@ module VagrantPlugins
|
||||||
forward_agent: ssh_info[:forward_agent],
|
forward_agent: ssh_info[:forward_agent],
|
||||||
forward_x11: ssh_info[:forward_x11],
|
forward_x11: ssh_info[:forward_x11],
|
||||||
proxy_command: ssh_info[:proxy_command],
|
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
|
# Render the template and output directly to STDOUT
|
||||||
template = "commands/ssh_config/config"
|
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
|
safe_puts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ module VagrantPlugins
|
||||||
return if !argv
|
return if !argv
|
||||||
|
|
||||||
# Validate the provisioners
|
# Validate the provisioners
|
||||||
validate_provisioner_flags!(options)
|
validate_provisioner_flags!(options, argv)
|
||||||
|
|
||||||
# Go over each VM and bring it up
|
# Go over each VM and bring it up
|
||||||
@logger.debug("'Up' each target VM...")
|
@logger.debug("'Up' each target VM...")
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
require "set"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module CommandUp
|
module CommandUp
|
||||||
module StartMixins
|
module StartMixins
|
||||||
|
@ -17,7 +19,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
parser.on("--provision-with x,y,z", Array,
|
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_types] = list.map { |type| type.to_sym }
|
||||||
options[:provision_enabled] = true
|
options[:provision_enabled] = true
|
||||||
options[:provision_ignore_sentinel] = true
|
options[:provision_ignore_sentinel] = true
|
||||||
|
@ -26,13 +28,26 @@ module VagrantPlugins
|
||||||
|
|
||||||
# This validates the provisioner flags and raises an exception
|
# This validates the provisioner flags and raises an exception
|
||||||
# if there are invalid ones.
|
# if there are invalid ones.
|
||||||
def validate_provisioner_flags!(options)
|
def validate_provisioner_flags!(options, argv)
|
||||||
(options[:provision_types] || []).each do |type|
|
if options[:provision_types].nil?
|
||||||
klass = Vagrant.plugin("2").manager.provisioners[type]
|
return
|
||||||
if !klass
|
end
|
||||||
raise Vagrant::Errors::ProvisionerFlagInvalid,
|
|
||||||
name: type.to_s
|
provisioner_names = Set.new
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -333,6 +333,7 @@ module VagrantPlugins
|
||||||
auth_methods: auth_methods,
|
auth_methods: auth_methods,
|
||||||
config: false,
|
config: false,
|
||||||
forward_agent: ssh_info[:forward_agent],
|
forward_agent: ssh_info[:forward_agent],
|
||||||
|
send_env: ssh_info[:forward_env],
|
||||||
keys: ssh_info[:private_key_path],
|
keys: ssh_info[:private_key_path],
|
||||||
keys_only: true,
|
keys_only: true,
|
||||||
paranoid: false,
|
paranoid: false,
|
||||||
|
@ -420,7 +421,7 @@ module VagrantPlugins
|
||||||
rescue Errno::EHOSTDOWN
|
rescue Errno::EHOSTDOWN
|
||||||
# This is raised if we get an ICMP DestinationUnknown error.
|
# This is raised if we get an ICMP DestinationUnknown error.
|
||||||
raise Vagrant::Errors::SSHHostDown
|
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.
|
# This is raised if we can't work out how to route traffic.
|
||||||
raise Vagrant::Errors::SSHNoRoute
|
raise Vagrant::Errors::SSHNoRoute
|
||||||
rescue Net::SSH::Exception => e
|
rescue Net::SSH::Exception => e
|
||||||
|
@ -611,6 +612,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
data = pty_stdout[/.*#{PTY_DELIM_START}(.*?)#{PTY_DELIM_END}/m, 1]
|
data = pty_stdout[/.*#{PTY_DELIM_START}(.*?)#{PTY_DELIM_END}/m, 1]
|
||||||
|
data ||= ""
|
||||||
@logger.debug("PTY stdout parsed: #{data}")
|
@logger.debug("PTY stdout parsed: #{data}")
|
||||||
yield :stdout, data if block_given?
|
yield :stdout, data if block_given?
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,6 +43,7 @@ module VagrantPlugins
|
||||||
# Got it! Let the user know what we're connecting to.
|
# Got it! Let the user know what we're connecting to.
|
||||||
@machine.ui.detail("WinRM address: #{shell.host}:#{shell.port}")
|
@machine.ui.detail("WinRM address: #{shell.host}:#{shell.port}")
|
||||||
@machine.ui.detail("WinRM username: #{shell.username}")
|
@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}")
|
@machine.ui.detail("WinRM transport: #{shell.config.transport}")
|
||||||
|
|
||||||
last_message = nil
|
last_message = nil
|
||||||
|
@ -136,10 +137,11 @@ module VagrantPlugins
|
||||||
error_key: nil, # use the error_class message key
|
error_key: nil, # use the error_class message key
|
||||||
good_exit: 0,
|
good_exit: 0,
|
||||||
shell: :powershell,
|
shell: :powershell,
|
||||||
|
interactive: false,
|
||||||
}.merge(opts || {})
|
}.merge(opts || {})
|
||||||
|
|
||||||
opts[:good_exit] = Array(opts[:good_exit])
|
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)
|
output = shell.send(opts[:shell], command, &block)
|
||||||
execution_output(output, opts)
|
execution_output(output, opts)
|
||||||
end
|
end
|
||||||
|
@ -193,9 +195,11 @@ module VagrantPlugins
|
||||||
# in place.
|
# in place.
|
||||||
#
|
#
|
||||||
# @return The wrapper command to execute
|
# @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__)
|
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"
|
guest_script_path = "c:/tmp/vagrant-elevated-shell.ps1"
|
||||||
file = Tempfile.new(["vagrant-elevated-shell", "ps1"])
|
file = Tempfile.new(["vagrant-elevated-shell", "ps1"])
|
||||||
begin
|
begin
|
||||||
|
@ -208,14 +212,16 @@ module VagrantPlugins
|
||||||
file.unlink
|
file.unlink
|
||||||
end
|
end
|
||||||
|
|
||||||
# convert to double byte unicode string then base64 encode
|
# Convert to double byte unicode string then base64 encode
|
||||||
# just like PowerShell -EncodedCommand expects
|
# just like PowerShell -EncodedCommand expects.
|
||||||
|
# Suppress the progress stream from leaking to stderr.
|
||||||
wrapped_encoded_command = Base64.strict_encode64(
|
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}\" " +
|
"powershell -executionpolicy bypass -file '#{guest_script_path}' " +
|
||||||
"-username \"#{shell.username}\" -password \"#{shell.password}\" " +
|
"-username '#{shell.username}' -password '#{shell.password}' " +
|
||||||
"-encoded_command \"#{wrapped_encoded_command}\""
|
"-encoded_command '#{wrapped_encoded_command}' " +
|
||||||
|
"-execution_time_limit '#{shell.execution_time_limit}'"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Handles the raw WinRM shell result and converts it to a
|
# Handles the raw WinRM shell result and converts it to a
|
||||||
|
|
|
@ -11,6 +11,7 @@ module VagrantPlugins
|
||||||
attr_accessor :timeout
|
attr_accessor :timeout
|
||||||
attr_accessor :transport
|
attr_accessor :transport
|
||||||
attr_accessor :ssl_peer_verification
|
attr_accessor :ssl_peer_verification
|
||||||
|
attr_accessor :execution_time_limit
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@username = UNSET_VALUE
|
@username = UNSET_VALUE
|
||||||
|
@ -23,6 +24,7 @@ module VagrantPlugins
|
||||||
@timeout = UNSET_VALUE
|
@timeout = UNSET_VALUE
|
||||||
@transport = UNSET_VALUE
|
@transport = UNSET_VALUE
|
||||||
@ssl_peer_verification = UNSET_VALUE
|
@ssl_peer_verification = UNSET_VALUE
|
||||||
|
@execution_time_limit = UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
|
@ -37,6 +39,7 @@ module VagrantPlugins
|
||||||
@retry_delay = 2 if @retry_delay == UNSET_VALUE
|
@retry_delay = 2 if @retry_delay == UNSET_VALUE
|
||||||
@timeout = 1800 if @timeout == UNSET_VALUE
|
@timeout = 1800 if @timeout == UNSET_VALUE
|
||||||
@ssl_peer_verification = true if @ssl_peer_verification == UNSET_VALUE
|
@ssl_peer_verification = true if @ssl_peer_verification == UNSET_VALUE
|
||||||
|
@execution_time_limit = "PT2H" if @execution_time_limit == UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
|
@ -49,6 +52,7 @@ module VagrantPlugins
|
||||||
errors << "winrm.max_tries cannot be nil." if @max_tries.nil?
|
errors << "winrm.max_tries cannot be nil." if @max_tries.nil?
|
||||||
errors << "winrm.retry_delay 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.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
|
unless @ssl_peer_verification == true || @ssl_peer_verification == false
|
||||||
errors << "winrm.ssl_peer_verification must be a boolean."
|
errors << "winrm.ssl_peer_verification must be a boolean."
|
||||||
end
|
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"
|
$task_name = "WinRM_Elevated_Shell"
|
||||||
$out_file = "$env:SystemRoot\Temp\WinRM_Elevated_Shell.log"
|
$out_file = "$env:SystemRoot\Temp\WinRM_Elevated_Shell.log"
|
||||||
|
|
||||||
|
@ -13,7 +25,7 @@ $task_xml = @'
|
||||||
<Principals>
|
<Principals>
|
||||||
<Principal id="Author">
|
<Principal id="Author">
|
||||||
<UserId>{username}</UserId>
|
<UserId>{username}</UserId>
|
||||||
<LogonType>Password</LogonType>
|
<LogonType><%= options[:interactive] ? 'InteractiveTokenOrPassword' : 'Password' %></LogonType>
|
||||||
<RunLevel>HighestAvailable</RunLevel>
|
<RunLevel>HighestAvailable</RunLevel>
|
||||||
</Principal>
|
</Principal>
|
||||||
</Principals>
|
</Principals>
|
||||||
|
@ -33,7 +45,7 @@ $task_xml = @'
|
||||||
<Hidden>false</Hidden>
|
<Hidden>false</Hidden>
|
||||||
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
||||||
<WakeToRun>false</WakeToRun>
|
<WakeToRun>false</WakeToRun>
|
||||||
<ExecutionTimeLimit>PT2H</ExecutionTimeLimit>
|
<ExecutionTimeLimit>{execution_time_limit}</ExecutionTimeLimit>
|
||||||
<Priority>4</Priority>
|
<Priority>4</Priority>
|
||||||
</Settings>
|
</Settings>
|
||||||
<Actions Context="Author">
|
<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("{arguments}", $arguments)
|
||||||
$task_xml = $task_xml.Replace("{username}", $username)
|
$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()
|
$schedule.Connect()
|
||||||
$task = $schedule.NewTask($null)
|
$task = $schedule.NewTask($null)
|
||||||
$task.XmlText = $task_xml
|
$task.XmlText = $task_xml
|
||||||
$folder = $schedule.GetFolder("\")
|
$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 = $folder.GetTask("\$task_name")
|
||||||
$registered_task.Run($null) | Out-Null
|
$registered_task.Run($null) | Out-Null
|
||||||
|
@ -71,7 +83,7 @@ function SlurpOutput($out_file, $cur_line) {
|
||||||
if (Test-Path $out_file) {
|
if (Test-Path $out_file) {
|
||||||
get-content $out_file | select -skip $cur_line | ForEach {
|
get-content $out_file | select -skip $cur_line | ForEach {
|
||||||
$cur_line += 1
|
$cur_line += 1
|
||||||
Write-Host "$_"
|
Write-Host "$_"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $cur_line
|
return $cur_line
|
||||||
|
|
|
@ -9,7 +9,7 @@ Vagrant::Util::SilenceWarnings.silence! do
|
||||||
require "winrm"
|
require "winrm"
|
||||||
end
|
end
|
||||||
|
|
||||||
require "winrm-fs/file_manager"
|
require "winrm-fs"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module CommunicatorWinRM
|
module CommunicatorWinRM
|
||||||
|
@ -23,6 +23,7 @@ module VagrantPlugins
|
||||||
HTTPClient::KeepAliveDisconnected,
|
HTTPClient::KeepAliveDisconnected,
|
||||||
WinRM::WinRMHTTPTransportError,
|
WinRM::WinRMHTTPTransportError,
|
||||||
WinRM::WinRMAuthorizationError,
|
WinRM::WinRMAuthorizationError,
|
||||||
|
WinRM::WinRMWSManFault,
|
||||||
Errno::EACCES,
|
Errno::EACCES,
|
||||||
Errno::EADDRINUSE,
|
Errno::EADDRINUSE,
|
||||||
Errno::ECONNREFUSED,
|
Errno::ECONNREFUSED,
|
||||||
|
@ -37,6 +38,7 @@ module VagrantPlugins
|
||||||
attr_reader :port
|
attr_reader :port
|
||||||
attr_reader :username
|
attr_reader :username
|
||||||
attr_reader :password
|
attr_reader :password
|
||||||
|
attr_reader :execution_time_limit
|
||||||
attr_reader :config
|
attr_reader :config
|
||||||
|
|
||||||
def initialize(host, port, config)
|
def initialize(host, port, config)
|
||||||
|
@ -47,12 +49,15 @@ module VagrantPlugins
|
||||||
@port = port
|
@port = port
|
||||||
@username = config.username
|
@username = config.username
|
||||||
@password = config.password
|
@password = config.password
|
||||||
|
@execution_time_limit = config.execution_time_limit
|
||||||
@config = config
|
@config = config
|
||||||
end
|
end
|
||||||
|
|
||||||
def powershell(command, &block)
|
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"
|
command << "\r\n"
|
||||||
|
# Ensure an exit code
|
||||||
command << "if ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
|
command << "if ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
|
||||||
execute_shell(command, :powershell, &block)
|
execute_shell(command, :powershell, &block)
|
||||||
end
|
end
|
||||||
|
|
|
@ -27,7 +27,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
machine.communicate.upload(temp.path, "/tmp/vagrant_network")
|
machine.communicate.upload(temp.path, "/tmp/vagrant_network")
|
||||||
machine.communicate.sudo("mv /tmp/vagrant_network /etc/netctl/#{network[:device]}")
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,45 +6,109 @@ module VagrantPlugins
|
||||||
module GuestDarwin
|
module GuestDarwin
|
||||||
module Cap
|
module Cap
|
||||||
class ConfigureNetworks
|
class ConfigureNetworks
|
||||||
|
@@logger = Log4r::Logger.new("vagrant::guest::darwin::configure_networks")
|
||||||
|
|
||||||
include Vagrant::Util
|
include Vagrant::Util
|
||||||
|
|
||||||
def self.configure_networks(machine, networks)
|
def self.configure_networks(machine, networks)
|
||||||
# Slightly different than other plugins, using the template to build commands
|
if !machine.provider.capability?(:nic_mac_addresses)
|
||||||
# rather than templating the files.
|
raise Vagrant::Errors::CantReadMACAddresses,
|
||||||
|
provider: machine.provider_name.to_s
|
||||||
|
end
|
||||||
|
|
||||||
machine.communicate.sudo("networksetup -detectnewhardware")
|
nic_mac_addresses = machine.provider.capability(:nic_mac_addresses)
|
||||||
machine.communicate.sudo("networksetup -listnetworkserviceorder > /tmp/vagrant.interfaces")
|
@@logger.debug("mac addresses: #{nic_mac_addresses.inspect}")
|
||||||
tmpints = File.join(Dir.tmpdir, File.basename("#{machine.id}.interfaces"))
|
|
||||||
machine.communicate.download("/tmp/vagrant.interfaces",tmpints)
|
|
||||||
|
|
||||||
devlist = []
|
mac_service_map = create_mac_service_map(machine)
|
||||||
ints = ::IO.read(tmpints)
|
|
||||||
|
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|
|
ints.split(/\n\n/m).each do |i|
|
||||||
if i.match(/Hardware/) and not i.match(/Ethernet/).nil?
|
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||||
devmap = {}
|
|
||||||
# Ethernet, should be 2 lines,
|
# Ethernet, should be 2 lines,
|
||||||
# (3) Thunderbolt Ethernet
|
# (3) Thunderbolt Ethernet
|
||||||
# (Hardware Port: Thunderbolt Ethernet, Device: en1)
|
# (Hardware Port: Thunderbolt Ethernet, Device: en1)
|
||||||
|
|
||||||
# multiline, should match "Thunderbolt Ethernet", "en1"
|
# multiline, should match "Thunderbolt Ethernet", "en1"
|
||||||
devicearry = i.match(/\([0-9]+\) (.+)\n.*Device: (.+)\)/m)
|
devicearry = i.match(/\([0-9]+\) (.+)\n.*Device: (.+)\)/m)
|
||||||
devmap[:interface] = devicearry[2]
|
service = devicearry[1]
|
||||||
devmap[:service] = devicearry[1]
|
interface = devicearry[2]
|
||||||
devlist << devmap
|
|
||||||
|
# Should map interface to service { "en1" => "Thunderbolt Ethernet" }
|
||||||
|
interface_map[interface] = service
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
File.delete(tmpints)
|
File.delete(tmp_ints)
|
||||||
|
|
||||||
networks.each do |network|
|
mac_service_map = {}
|
||||||
service_name = devlist[network[:interface]][:service]
|
macs = ::IO.read(tmp_hw)
|
||||||
if network[:type].to_sym == :static
|
macs.split(/\n\n/m).each do |i|
|
||||||
command = "networksetup -setmanual \"#{service_name}\" #{network[:ip]} #{network[:netmask]}"
|
if i.match(/Hardware/) && i.match(/Ethernet/)
|
||||||
elsif network[:type].to_sym == :dhcp
|
# Ethernet, should be 3 lines,
|
||||||
command = "networksetup -setdhcp \"#{service_name}\""
|
# 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
|
end
|
||||||
|
|
||||||
machine.communicate.sudo(command)
|
|
||||||
end
|
end
|
||||||
|
File.delete(tmp_hw)
|
||||||
|
|
||||||
|
mac_service_map
|
||||||
end
|
end
|
||||||
end
|
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
|
module GuestDebian
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < Vagrant.plugin("2", :guest)
|
||||||
def detect?(machine)
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,6 +30,11 @@ module VagrantPlugins
|
||||||
require_relative "cap/rsync"
|
require_relative "cap/rsync"
|
||||||
Cap::RSync
|
Cap::RSync
|
||||||
end
|
end
|
||||||
|
|
||||||
|
guest_capability("debian", "smb_install") do
|
||||||
|
require_relative "cap/smb"
|
||||||
|
Cap::SMB
|
||||||
|
end
|
||||||
end
|
end
|
||||||
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
|
def update_etc_hosts
|
||||||
ip_address = '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
ip_address = '([0-9]{1,3}\.){3}[0-9]{1,3}'
|
||||||
search = "^(#{ip_address})\\s+#{Regexp.escape(current_hostname)}(\\s.*)?$"
|
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('@')
|
expression = ['s', search, replace, 'g'].join('@')
|
||||||
|
|
||||||
sudo("sed -ri '#{expression}' /etc/hosts")
|
sudo("sed -ri '#{expression}' /etc/hosts")
|
||||||
|
@ -72,4 +72,4 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -109,13 +109,23 @@ module VagrantPlugins
|
||||||
# SSH never dies.
|
# SSH never dies.
|
||||||
interfaces.each do |interface|
|
interfaces.each do |interface|
|
||||||
retryable(on: Vagrant::Errors::VagrantError, tries: 3, sleep: 2) do
|
retryable(on: Vagrant::Errors::VagrantError, tries: 3, sleep: 2) do
|
||||||
machine.communicate.sudo("cat /tmp/vagrant-network-entry_#{interface} >> #{network_scripts_dir}/ifcfg-#{interface}")
|
machine.communicate.sudo(<<-SCRIPT, error_check: true)
|
||||||
machine.communicate.sudo("! which nmcli >/dev/null 2>&1 || nmcli c reload #{interface}")
|
cat /tmp/vagrant-network-entry_#{interface} >> #{network_scripts_dir}/ifcfg-#{interface}
|
||||||
machine.communicate.sudo("/sbin/ifdown #{interface}", error_check: true)
|
|
||||||
machine.communicate.sudo("/sbin/ifup #{interface}")
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ module VagrantPlugins
|
||||||
module GuestFedora
|
module GuestFedora
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < Vagrant.plugin("2", :guest)
|
||||||
def detect?(machine)
|
def detect?(machine)
|
||||||
machine.communicate.test("grep 'Fedora release 1[6789]\\|Fedora release 2[0-9]' /etc/redhat-release")
|
machine.communicate.test("grep 'Fedora release' /etc/redhat-release")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -33,10 +33,11 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit an upstart event if we can
|
# 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 <<-SCRIPT
|
||||||
machine.communicate.sudo(
|
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}")
|
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||||
end
|
fi
|
||||||
|
SCRIPT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,17 +24,14 @@ module VagrantPlugins
|
||||||
mount_gid = "`getent group #{options[:group]} | cut -d: -f3`"
|
mount_gid = "`getent group #{options[:group]} | cut -d: -f3`"
|
||||||
mount_gid_old = "`id -g #{options[:group]}`"
|
mount_gid_old = "`id -g #{options[:group]}`"
|
||||||
end
|
end
|
||||||
|
|
||||||
smb_password = Shellwords.shellescape(options[:smb_password])
|
|
||||||
|
|
||||||
# If a domain is provided in the username, separate it
|
# If a domain is provided in the username, separate it
|
||||||
username, domain = (options[:smb_username] || '').split('@', 2)
|
username, domain = (options[:smb_username] || '').split('@', 2)
|
||||||
|
smb_password = options[:smb_password]
|
||||||
|
|
||||||
options[:mount_options] ||= []
|
options[:mount_options] ||= []
|
||||||
options[:mount_options] << "sec=ntlm"
|
options[:mount_options] << "sec=ntlm"
|
||||||
options[:mount_options] << "username=#{username}"
|
options[:mount_options] << "credentials=/etc/smb_creds_#{name}"
|
||||||
options[:mount_options] << "password=#{smb_password}"
|
|
||||||
options[:mount_options] << "domain=#{domain}" if domain
|
|
||||||
|
|
||||||
# First mount command uses getent to get the group
|
# First mount command uses getent to get the group
|
||||||
mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"
|
mount_options = "-o uid=#{mount_uid},gid=#{mount_gid}"
|
||||||
|
@ -49,6 +46,16 @@ module VagrantPlugins
|
||||||
# Create the guest path if it doesn't exist
|
# Create the guest path if it doesn't exist
|
||||||
machine.communicate.sudo("mkdir -p #{expanded_guest_path}")
|
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
|
# Attempt to mount the folder. We retry here a few times because
|
||||||
# it can fail early on.
|
# it can fail early on.
|
||||||
attempts = 0
|
attempts = 0
|
||||||
|
@ -86,10 +93,11 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit an upstart event if we can
|
# 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 <<-SCRIPT
|
||||||
machine.communicate.sudo(
|
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}")
|
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||||
end
|
fi
|
||||||
|
SCRIPT
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -80,10 +80,11 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit an upstart event if we can
|
# 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 <<-SCRIPT
|
||||||
machine.communicate.sudo(
|
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}")
|
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||||
end
|
fi
|
||||||
|
SCRIPT
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.unmount_virtualbox_shared_folder(machine, guestpath, options)
|
def self.unmount_virtualbox_shared_folder(machine, guestpath, options)
|
||||||
|
|
|
@ -10,8 +10,11 @@ module VagrantPlugins
|
||||||
|
|
||||||
machine.communicate.tap do |comm|
|
machine.communicate.tap do |comm|
|
||||||
if comm.test("test -f ~/.ssh/authorized_keys")
|
if comm.test("test -f ~/.ssh/authorized_keys")
|
||||||
comm.execute(
|
comm.execute(<<SCRIPT)
|
||||||
"sed -i '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys")
|
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
|
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"
|
require_relative "cap/network_scripts_dir"
|
||||||
Cap::NetworkScriptsDir
|
Cap::NetworkScriptsDir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
guest_capability("pld", "flavor") do
|
||||||
|
require_relative "cap/flavor"
|
||||||
|
Cap::Flavor
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,11 @@ module VagrantPlugins
|
||||||
module Cap
|
module Cap
|
||||||
class NFSClient
|
class NFSClient
|
||||||
def self.nfs_client_install(machine)
|
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)
|
restart_nfs(machine)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,11 @@ module VagrantPlugins
|
||||||
class RSync
|
class RSync
|
||||||
def self.rsync_install(machine)
|
def self.rsync_install(machine)
|
||||||
machine.communicate.tap do |comm|
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,6 +45,10 @@ module VagrantPlugins
|
||||||
require_relative "cap/rsync"
|
require_relative "cap/rsync"
|
||||||
Cap::RSync
|
Cap::RSync
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.dnf?(machine)
|
||||||
|
machine.communicate.test("/usr/bin/which -s dnf")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
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 VagrantPlugins
|
||||||
module GuestDebian8
|
module GuestSlackware
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < Vagrant.plugin("2", :guest)
|
||||||
def detect?(machine)
|
def detect?(machine)
|
||||||
machine.communicate.test("cat /etc/issue | grep 'Debian' | grep '8'")
|
machine.communicate.test("cat /etc/slackware-version")
|
||||||
end
|
end
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def update_etc_hostname
|
def update_etc_hostname
|
||||||
return super unless vivid?
|
return super unless systemd?
|
||||||
sudo("hostnamectl set-hostname '#{short_hostname}'")
|
sudo("hostnamectl set-hostname '#{short_hostname}'")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ module VagrantPlugins
|
||||||
if hardy?
|
if hardy?
|
||||||
# hostname.sh returns 1, so use `true` to get a 0 exitcode
|
# hostname.sh returns 1, so use `true` to get a 0 exitcode
|
||||||
sudo("/etc/init.d/hostname.sh start; true")
|
sudo("/etc/init.d/hostname.sh start; true")
|
||||||
elsif vivid?
|
elsif systemd?
|
||||||
# Service runs via hostnamectl
|
# Service runs via hostnamectl
|
||||||
else
|
else
|
||||||
sudo("service hostname start")
|
sudo("service hostname start")
|
||||||
|
@ -26,19 +26,25 @@ module VagrantPlugins
|
||||||
os_version("hardy")
|
os_version("hardy")
|
||||||
end
|
end
|
||||||
|
|
||||||
def vivid?
|
|
||||||
os_version("vivid")
|
|
||||||
end
|
|
||||||
|
|
||||||
def renew_dhcp
|
def renew_dhcp
|
||||||
sudo("ifdown -a; ifup -a; ifup -a --allow=hotplug")
|
sudo("ifdown -a; ifup -a; ifup -a --allow=hotplug")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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)
|
def os_version(name)
|
||||||
machine.communicate.test("[ `lsb_release -c -s` = #{name} ]")
|
machine.communicate.test("[ `lsb_release -c -s` = #{name} ]")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def systemd?
|
||||||
|
init_package == 'systemd'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -53,7 +53,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
def self.create_vm_interface_map(machine, guest_network)
|
def self.create_vm_interface_map(machine, guest_network)
|
||||||
if !machine.provider.capability?(:nic_mac_addresses)
|
if !machine.provider.capability?(:nic_mac_addresses)
|
||||||
raise Errors::CantReadMACAddresses,
|
raise Vagrant::Errors::CantReadMACAddresses,
|
||||||
provider: machine.provider_name.to_s
|
provider: machine.provider_name.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,17 @@ module VagrantPlugins
|
||||||
module GuestWindows
|
module GuestWindows
|
||||||
module Cap
|
module Cap
|
||||||
class RSync
|
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)
|
def self.rsync_pre(machine, opts)
|
||||||
machine.communicate.tap do |comm|
|
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]}'")
|
comm.execute("mkdir '#{opts[:guestpath]}'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,10 +6,6 @@ module VagrantPlugins
|
||||||
error_namespace("vagrant_windows.errors")
|
error_namespace("vagrant_windows.errors")
|
||||||
end
|
end
|
||||||
|
|
||||||
class CantReadMACAddresses < WindowsError
|
|
||||||
error_key(:cant_read_mac_addresses)
|
|
||||||
end
|
|
||||||
|
|
||||||
class NetworkWinRMRequired < WindowsError
|
class NetworkWinRMRequired < WindowsError
|
||||||
error_key(:network_winrm_required)
|
error_key(:network_winrm_required)
|
||||||
end
|
end
|
||||||
|
|
|
@ -64,6 +64,11 @@ module VagrantPlugins
|
||||||
Cap::MountSharedFolder
|
Cap::MountSharedFolder
|
||||||
end
|
end
|
||||||
|
|
||||||
|
guest_capability(:windows, :rsync_scrub_guestpath) do
|
||||||
|
require_relative "cap/rsync"
|
||||||
|
Cap::RSync
|
||||||
|
end
|
||||||
|
|
||||||
guest_capability(:windows, :rsync_pre) do
|
guest_capability(:windows, :rsync_pre) do
|
||||||
require_relative "cap/rsync"
|
require_relative "cap/rsync"
|
||||||
Cap::RSync
|
Cap::RSync
|
||||||
|
|
|
@ -2,6 +2,7 @@ require "pathname"
|
||||||
require "tempfile"
|
require "tempfile"
|
||||||
|
|
||||||
require "vagrant/util/downloader"
|
require "vagrant/util/downloader"
|
||||||
|
require "vagrant/util/file_checksum"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
|
@ -10,8 +11,9 @@ module VagrantPlugins
|
||||||
class ProviderInstallVirtualBox
|
class ProviderInstallVirtualBox
|
||||||
# The URL to download VirtualBox is hardcoded so we can have a
|
# The URL to download VirtualBox is hardcoded so we can have a
|
||||||
# known-good version to download.
|
# known-good version to download.
|
||||||
URL = "http://download.virtualbox.org/virtualbox/5.0.8/VirtualBox-5.0.8-103449-OSX.dmg".freeze
|
URL = "http://download.virtualbox.org/virtualbox/5.0.10/VirtualBox-5.0.10-104061-OSX.dmg".freeze
|
||||||
VERSION = "5.0.8".freeze
|
VERSION = "5.0.10".freeze
|
||||||
|
SHA256SUM = "62f933115498e51ddf5f2dab47dc1eebb42eb78ea1a7665cb91c53edacc847c6".freeze
|
||||||
|
|
||||||
def self.provider_install_virtualbox(env)
|
def self.provider_install_virtualbox(env)
|
||||||
tf = Tempfile.new("vagrant")
|
tf = Tempfile.new("vagrant")
|
||||||
|
@ -29,6 +31,15 @@ module VagrantPlugins
|
||||||
dl = Vagrant::Util::Downloader.new(URL, tf.path, ui: ui)
|
dl = Vagrant::Util::Downloader.new(URL, tf.path, ui: ui)
|
||||||
dl.download!
|
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
|
# Launch it
|
||||||
ui.output(I18n.t(
|
ui.output(I18n.t(
|
||||||
"vagrant.hosts.darwin.virtualbox_install_install"))
|
"vagrant.hosts.darwin.virtualbox_install_install"))
|
||||||
|
|
|
@ -5,17 +5,35 @@ module VagrantPlugins
|
||||||
module Cap
|
module Cap
|
||||||
class RDP
|
class RDP
|
||||||
def self.rdp_client(env, rdp_info)
|
def self.rdp_client(env, rdp_info)
|
||||||
if !Vagrant::Util::Which.which("rdesktop")
|
# Detect if an RDP client is available.
|
||||||
raise Vagrant::Errors::LinuxRDesktopNotFound
|
# Prefer xfreerdp as it supports newer versions of RDP.
|
||||||
end
|
rdp_client =
|
||||||
|
if Vagrant::Util::Which.which("xfreerdp")
|
||||||
|
"xfreerdp"
|
||||||
|
elsif Vagrant::Util::Which.which("rdesktop")
|
||||||
|
"rdesktop"
|
||||||
|
else
|
||||||
|
raise Vagrant::Errors::LinuxRDPClientNotFound
|
||||||
|
end
|
||||||
|
|
||||||
args = []
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ module VagrantPlugins
|
||||||
module Cap
|
module Cap
|
||||||
class NFS
|
class NFS
|
||||||
def self.nfs_check_command(env)
|
def self.nfs_check_command(env)
|
||||||
"pidof nfsd >/dev/null"
|
"/sbin/pidof nfsd >/dev/null"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.nfs_start_command(env)
|
def self.nfs_start_command(env)
|
||||||
|
|
|
@ -4,7 +4,7 @@ module VagrantPlugins
|
||||||
module HostSlackware
|
module HostSlackware
|
||||||
class Host < Vagrant.plugin("2", :host)
|
class Host < Vagrant.plugin("2", :host)
|
||||||
def detect?(env)
|
def detect?(env)
|
||||||
return File.exists?("/etc/slackware-release") ||
|
return File.exists?("/etc/slackware-version") ||
|
||||||
!Dir.glob("/usr/lib/setup/Plamo-*").empty?
|
!Dir.glob("/usr/lib/setup/Plamo-*").empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.nfs_check_command(env)
|
def self.nfs_check_command(env)
|
||||||
"pidof nfsd > /dev/null"
|
"/sbin/service nfsserver status"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.nfs_start_command(env)
|
def self.nfs_start_command(env)
|
||||||
|
|
|
@ -2,6 +2,8 @@ require "pathname"
|
||||||
require "tempfile"
|
require "tempfile"
|
||||||
|
|
||||||
require "vagrant/util/downloader"
|
require "vagrant/util/downloader"
|
||||||
|
require "vagrant/util/file_checksum"
|
||||||
|
require "vagrant/util/powershell"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
|
@ -10,8 +12,9 @@ module VagrantPlugins
|
||||||
class ProviderInstallVirtualBox
|
class ProviderInstallVirtualBox
|
||||||
# The URL to download VirtualBox is hardcoded so we can have a
|
# The URL to download VirtualBox is hardcoded so we can have a
|
||||||
# known-good version to download.
|
# known-good version to download.
|
||||||
URL = "http://download.virtualbox.org/virtualbox/5.0.8/VirtualBox-5.0.8-103449-Win.exe".freeze
|
URL = "http://download.virtualbox.org/virtualbox/5.0.10/VirtualBox-5.0.10-104061-Win.exe".freeze
|
||||||
VERSION = "5.0.8".freeze
|
VERSION = "5.0.10".freeze
|
||||||
|
SHA256SUM = "3e5ed8fe4ada6eef8dfb4fe6fd79fcab4b242acf799f7d3ab4a17b43838b1e04".freeze
|
||||||
|
|
||||||
def self.provider_install_virtualbox(env)
|
def self.provider_install_virtualbox(env)
|
||||||
tf = Tempfile.new("vagrant")
|
tf = Tempfile.new("vagrant")
|
||||||
|
@ -29,13 +32,22 @@ module VagrantPlugins
|
||||||
dl = Vagrant::Util::Downloader.new(URL, tf.path, ui: ui)
|
dl = Vagrant::Util::Downloader.new(URL, tf.path, ui: ui)
|
||||||
dl.download!
|
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
|
# Launch it
|
||||||
ui.output(I18n.t(
|
ui.output(I18n.t(
|
||||||
"vagrant.hosts.windows.virtualbox_install_install"))
|
"vagrant.hosts.windows.virtualbox_install_install"))
|
||||||
ui.detail(I18n.t(
|
ui.detail(I18n.t(
|
||||||
"vagrant.hosts.windows.virtualbox_install_install_detail"))
|
"vagrant.hosts.windows.virtualbox_install_install_detail"))
|
||||||
script = File.expand_path("../../scripts/install_virtualbox.ps1", __FILE__)
|
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
|
if result.exit_code != 0
|
||||||
raise Vagrant::Errors::ProviderInstallFailed,
|
raise Vagrant::Errors::ProviderInstallFailed,
|
||||||
provider: "virtualbox",
|
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"
|
require_relative "cap/rdp"
|
||||||
Cap::RDP
|
Cap::RDP
|
||||||
end
|
end
|
||||||
|
|
||||||
|
host_capability("windows", "ps_client") do
|
||||||
|
require_relative "cap/ps"
|
||||||
|
Cap::PS
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,7 @@ module VagrantPlugins
|
||||||
attr_accessor :private_key_path
|
attr_accessor :private_key_path
|
||||||
attr_accessor :forward_agent
|
attr_accessor :forward_agent
|
||||||
attr_accessor :forward_x11
|
attr_accessor :forward_x11
|
||||||
|
attr_accessor :forward_env
|
||||||
attr_accessor :shell
|
attr_accessor :shell
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
@ -26,6 +27,7 @@ module VagrantPlugins
|
||||||
@private_key_path = UNSET_VALUE
|
@private_key_path = UNSET_VALUE
|
||||||
@forward_agent = UNSET_VALUE
|
@forward_agent = UNSET_VALUE
|
||||||
@forward_x11 = UNSET_VALUE
|
@forward_x11 = UNSET_VALUE
|
||||||
|
@forward_env = UNSET_VALUE
|
||||||
@shell = UNSET_VALUE
|
@shell = UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,6 +39,7 @@ module VagrantPlugins
|
||||||
new.ssh.private_key_path = @private_key_path if @private_key_path != UNSET_VALUE
|
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_agent = @forward_agent if @forward_agent != UNSET_VALUE
|
||||||
new.ssh.forward_x11 = @forward_x11 if @forward_x11 != 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
|
new.ssh.shell = @shell if @shell != UNSET_VALUE
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ module VagrantPlugins
|
||||||
class SSHConfig < SSHConnectConfig
|
class SSHConfig < SSHConnectConfig
|
||||||
attr_accessor :forward_agent
|
attr_accessor :forward_agent
|
||||||
attr_accessor :forward_x11
|
attr_accessor :forward_x11
|
||||||
|
attr_accessor :forward_env
|
||||||
attr_accessor :guest_port
|
attr_accessor :guest_port
|
||||||
attr_accessor :keep_alive
|
attr_accessor :keep_alive
|
||||||
attr_accessor :shell
|
attr_accessor :shell
|
||||||
|
@ -22,6 +23,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
@forward_agent = UNSET_VALUE
|
@forward_agent = UNSET_VALUE
|
||||||
@forward_x11 = UNSET_VALUE
|
@forward_x11 = UNSET_VALUE
|
||||||
|
@forward_env = UNSET_VALUE
|
||||||
@guest_port = UNSET_VALUE
|
@guest_port = UNSET_VALUE
|
||||||
@keep_alive = UNSET_VALUE
|
@keep_alive = UNSET_VALUE
|
||||||
@proxy_command = UNSET_VALUE
|
@proxy_command = UNSET_VALUE
|
||||||
|
@ -45,6 +47,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
@forward_agent = false if @forward_agent == UNSET_VALUE
|
@forward_agent = false if @forward_agent == UNSET_VALUE
|
||||||
@forward_x11 = false if @forward_x11 == 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
|
@guest_port = 22 if @guest_port == UNSET_VALUE
|
||||||
@keep_alive = true if @keep_alive == UNSET_VALUE
|
@keep_alive = true if @keep_alive == UNSET_VALUE
|
||||||
@proxy_command = nil if @proxy_command == UNSET_VALUE
|
@proxy_command = nil if @proxy_command == UNSET_VALUE
|
||||||
|
|
|
@ -416,7 +416,8 @@ module VagrantPlugins
|
||||||
host_ip: "127.0.0.1",
|
host_ip: "127.0.0.1",
|
||||||
id: "winrm",
|
id: "winrm",
|
||||||
auto_correct: true
|
auto_correct: true
|
||||||
|
end
|
||||||
|
if !@__networks["forwarded_port-winrm-ssl"]
|
||||||
network :forwarded_port,
|
network :forwarded_port,
|
||||||
guest: 5986,
|
guest: 5986,
|
||||||
host: 55986,
|
host: 55986,
|
||||||
|
@ -697,7 +698,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
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(
|
machine.ui.warn(I18n.t(
|
||||||
"vagrant.config.vm.network_ip_ends_in_one"))
|
"vagrant.config.vm.network_ip_ends_in_one"))
|
||||||
end
|
end
|
||||||
|
|
|
@ -156,12 +156,12 @@ module VagrantPlugins
|
||||||
b3.use Call, DestroyConfirm do |env3, b4|
|
b3.use Call, DestroyConfirm do |env3, b4|
|
||||||
if env3[:result]
|
if env3[:result]
|
||||||
b4.use ConfigValidate
|
b4.use ConfigValidate
|
||||||
|
b4.use ProvisionerCleanup, :before
|
||||||
b4.use EnvSet, force_halt: true
|
b4.use EnvSet, force_halt: true
|
||||||
b4.use action_halt
|
b4.use action_halt
|
||||||
b4.use HostMachineSyncFoldersDisable
|
b4.use HostMachineSyncFoldersDisable
|
||||||
b4.use Destroy
|
b4.use Destroy
|
||||||
b4.use DestroyBuildImage
|
b4.use DestroyBuildImage
|
||||||
b4.use ProvisionerCleanup
|
|
||||||
else
|
else
|
||||||
b4.use Message,
|
b4.use Message,
|
||||||
I18n.t("docker_provider.messages.will_not_destroy")
|
I18n.t("docker_provider.messages.will_not_destroy")
|
||||||
|
|
|
@ -38,6 +38,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
b2.use ConfigValidate
|
b2.use ConfigValidate
|
||||||
|
b2.use ProvisionerCleanup, :before
|
||||||
b2.use StopInstance
|
b2.use StopInstance
|
||||||
b2.use DeleteVM
|
b2.use DeleteVM
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,8 +16,9 @@ module VagrantPlugins
|
||||||
raise Errors::WindowsRequired
|
raise Errors::WindowsRequired
|
||||||
end
|
end
|
||||||
|
|
||||||
if !Vagrant::Util::Platform.windows_admin?
|
if !Vagrant::Util::Platform.windows_admin? and
|
||||||
raise Errors::AdminRequired
|
!Vagrant::Util::Platform.windows_hyperv_admin?
|
||||||
|
raise Errors::AdminRequired
|
||||||
end
|
end
|
||||||
|
|
||||||
if !Vagrant::Util::PowerShell.available?
|
if !Vagrant::Util::PowerShell.available?
|
||||||
|
|
|
@ -7,9 +7,19 @@ Param(
|
||||||
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
||||||
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
||||||
|
|
||||||
|
$ip_address = ""
|
||||||
$vm = Get-VM -Id $VmId -ErrorAction "Stop"
|
$vm = Get-VM -Id $VmId -ErrorAction "Stop"
|
||||||
$network = Get-VMNetworkAdapter -VM $vm
|
$networks = Get-VMNetworkAdapter -VM $vm
|
||||||
$ip_address = $network.IpAddresses[0]
|
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 = @{
|
$resultHash = @{
|
||||||
ip = "$ip_address"
|
ip = "$ip_address"
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ try {
|
||||||
$VM = Get-VM -Id $VmId -ErrorAction "Stop"
|
$VM = Get-VM -Id $VmId -ErrorAction "Stop"
|
||||||
$State = $VM.state
|
$State = $VM.state
|
||||||
$Status = $VM.status
|
$Status = $VM.status
|
||||||
} catch [Microsoft.HyperV.PowerShell.VirtualizationOperationFailedException] {
|
} catch [Microsoft.HyperV.PowerShell.VirtualizationException] {
|
||||||
$State = "not_created"
|
$State = "not_created"
|
||||||
$Status = $State
|
$Status = $State
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue