vagrant-unbundled 2.2.7.0 → 2.2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. checksums.yaml +4 -4
  2. data/.hashibot.hcl +2 -0
  3. data/CHANGELOG.md +228 -0
  4. data/Gemfile +1 -1
  5. data/README.md +9 -51
  6. data/RELEASE.md +1 -1
  7. data/bin/vagrant +50 -1
  8. data/contrib/README.md +1 -0
  9. data/contrib/sudoers/linux-suse +2 -2
  10. data/contrib/zsh/_vagrant +738 -0
  11. data/contrib/zsh/generate_zsh_completion.rb +165 -0
  12. data/lib/vagrant.rb +28 -5
  13. data/lib/vagrant/action.rb +7 -0
  14. data/lib/vagrant/action/builder.rb +184 -38
  15. data/lib/vagrant/action/builtin/box_add.rb +24 -8
  16. data/lib/vagrant/action/builtin/box_check_outdated.rb +2 -1
  17. data/lib/vagrant/action/builtin/cleanup_disks.rb +56 -0
  18. data/lib/vagrant/action/builtin/cloud_init_setup.rb +122 -0
  19. data/lib/vagrant/action/builtin/cloud_init_wait.rb +30 -0
  20. data/lib/vagrant/action/builtin/delayed.rb +26 -0
  21. data/lib/vagrant/action/builtin/disk.rb +14 -1
  22. data/lib/vagrant/action/builtin/handle_box.rb +3 -1
  23. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +28 -9
  24. data/lib/vagrant/action/builtin/has_provisioner.rb +36 -0
  25. data/lib/vagrant/action/builtin/mixin_provisioners.rb +1 -0
  26. data/lib/vagrant/action/builtin/mixin_synced_folders.rb +20 -21
  27. data/lib/vagrant/action/builtin/set_hostname.rb +5 -1
  28. data/lib/vagrant/action/builtin/synced_folders.rb +16 -0
  29. data/lib/vagrant/action/builtin/trigger.rb +37 -0
  30. data/lib/vagrant/action/hook.rb +76 -23
  31. data/lib/vagrant/action/runner.rb +12 -27
  32. data/lib/vagrant/action/warden.rb +28 -31
  33. data/lib/vagrant/box.rb +11 -4
  34. data/lib/vagrant/box_collection.rb +1 -1
  35. data/lib/vagrant/bundler.rb +310 -61
  36. data/lib/vagrant/cli.rb +4 -2
  37. data/lib/vagrant/environment.rb +1 -0
  38. data/lib/vagrant/errors.rb +69 -1
  39. data/lib/vagrant/machine.rb +64 -11
  40. data/lib/vagrant/machine_index.rb +28 -1
  41. data/lib/vagrant/patches/net-ssh.rb +186 -0
  42. data/lib/vagrant/plugin/manager.rb +45 -16
  43. data/lib/vagrant/plugin/v2/command.rb +7 -2
  44. data/lib/vagrant/plugin/v2/components.rb +6 -0
  45. data/lib/vagrant/plugin/v2/manager.rb +67 -0
  46. data/lib/vagrant/plugin/v2/plugin.rb +13 -0
  47. data/lib/vagrant/plugin/v2/synced_folder.rb +50 -0
  48. data/lib/vagrant/plugin/v2/trigger.rb +64 -25
  49. data/lib/vagrant/shared_helpers.rb +36 -0
  50. data/lib/vagrant/ui.rb +43 -2
  51. data/lib/vagrant/util.rb +2 -0
  52. data/lib/vagrant/util/ansi_escape_code_remover.rb +1 -1
  53. data/lib/vagrant/util/caps.rb +48 -0
  54. data/lib/vagrant/util/credential_scrubber.rb +1 -1
  55. data/lib/vagrant/util/curl_helper.rb +12 -8
  56. data/lib/vagrant/util/directory.rb +19 -0
  57. data/lib/vagrant/util/downloader.rb +10 -5
  58. data/lib/vagrant/util/guest_hosts.rb +68 -0
  59. data/lib/vagrant/util/guest_inspection.rb +9 -1
  60. data/lib/vagrant/util/install_cli_autocomplete.rb +118 -0
  61. data/lib/vagrant/util/io.rb +7 -27
  62. data/lib/vagrant/util/ipv4_interfaces.rb +15 -0
  63. data/lib/vagrant/util/is_port_open.rb +8 -19
  64. data/lib/vagrant/util/map_command_options.rb +33 -0
  65. data/lib/vagrant/util/mime.rb +92 -0
  66. data/lib/vagrant/util/network_ip.rb +11 -1
  67. data/lib/vagrant/util/numeric.rb +28 -0
  68. data/lib/vagrant/util/platform.rb +10 -2
  69. data/lib/vagrant/util/powershell.rb +31 -15
  70. data/lib/vagrant/util/subprocess.rb +9 -1
  71. data/lib/vagrant/util/template_renderer.rb +2 -2
  72. data/lib/vagrant/util/uploader.rb +7 -4
  73. data/lib/vagrant/vagrantfile.rb +2 -2
  74. data/plugins/commands/autocomplete/command/install.rb +49 -0
  75. data/plugins/commands/autocomplete/command/root.rb +64 -0
  76. data/plugins/commands/autocomplete/plugin.rb +18 -0
  77. data/plugins/commands/cap/command.rb +5 -1
  78. data/plugins/commands/cloud/auth/login.rb +20 -23
  79. data/plugins/commands/cloud/auth/logout.rb +2 -10
  80. data/plugins/commands/cloud/auth/middleware/add_authentication.rb +60 -31
  81. data/plugins/commands/cloud/auth/middleware/add_downloader_authentication.rb +64 -0
  82. data/plugins/commands/cloud/auth/whoami.rb +18 -20
  83. data/plugins/commands/cloud/box/create.rb +33 -29
  84. data/plugins/commands/cloud/box/delete.rb +30 -24
  85. data/plugins/commands/cloud/box/show.rb +41 -31
  86. data/plugins/commands/cloud/box/update.rb +34 -26
  87. data/plugins/commands/cloud/client/client.rb +55 -79
  88. data/plugins/commands/cloud/list.rb +3 -4
  89. data/plugins/commands/cloud/locales/en.yml +15 -11
  90. data/plugins/commands/cloud/plugin.rb +10 -0
  91. data/plugins/commands/cloud/provider/create.rb +38 -28
  92. data/plugins/commands/cloud/provider/delete.rb +39 -29
  93. data/plugins/commands/cloud/provider/update.rb +37 -28
  94. data/plugins/commands/cloud/provider/upload.rb +53 -33
  95. data/plugins/commands/cloud/publish.rb +193 -106
  96. data/plugins/commands/cloud/search.rb +34 -21
  97. data/plugins/commands/cloud/util.rb +273 -161
  98. data/plugins/commands/cloud/version/create.rb +33 -28
  99. data/plugins/commands/cloud/version/delete.rb +35 -28
  100. data/plugins/commands/cloud/version/release.rb +35 -29
  101. data/plugins/commands/cloud/version/revoke.rb +36 -29
  102. data/plugins/commands/cloud/version/update.rb +29 -25
  103. data/plugins/commands/destroy/command.rb +7 -7
  104. data/plugins/commands/login/plugin.rb +0 -13
  105. data/plugins/commands/ssh_config/command.rb +1 -1
  106. data/plugins/communicators/ssh/communicator.rb +25 -24
  107. data/plugins/communicators/winrm/config.rb +1 -1
  108. data/plugins/communicators/winrm/helper.rb +1 -1
  109. data/plugins/communicators/winrm/shell.rb +1 -1
  110. data/plugins/communicators/winssh/communicator.rb +126 -38
  111. data/plugins/communicators/winssh/config.rb +3 -7
  112. data/plugins/guests/alpine/cap/change_host_name.rb +10 -11
  113. data/plugins/guests/alpine/cap/configure_networks.rb +1 -1
  114. data/plugins/guests/alt/cap/change_host_name.rb +40 -53
  115. data/plugins/guests/arch/cap/change_host_name.rb +5 -14
  116. data/plugins/guests/arch/cap/configure_networks.rb +27 -10
  117. data/plugins/guests/arch/cap/smb.rb +1 -1
  118. data/plugins/guests/atomic/cap/change_host_name.rb +5 -14
  119. data/plugins/guests/centos/cap/flavor.rb +24 -0
  120. data/plugins/guests/centos/guest.rb +9 -0
  121. data/plugins/guests/centos/plugin.rb +20 -0
  122. data/plugins/guests/darwin/cap/change_host_name.rb +10 -6
  123. data/plugins/guests/darwin/cap/darwin_version.rb +40 -0
  124. data/plugins/guests/darwin/cap/mount_smb_shared_folder.rb +1 -1
  125. data/plugins/guests/darwin/cap/mount_vmware_shared_folder.rb +33 -10
  126. data/plugins/guests/darwin/plugin.rb +15 -0
  127. data/plugins/guests/debian/cap/change_host_name.rb +12 -11
  128. data/plugins/guests/debian/cap/configure_networks.rb +14 -6
  129. data/plugins/guests/esxi/cap/public_key.rb +3 -1
  130. data/plugins/guests/fedora/guest.rb +4 -4
  131. data/plugins/guests/freebsd/cap/change_host_name.rb +10 -6
  132. data/plugins/guests/gentoo/cap/change_host_name.rb +14 -22
  133. data/plugins/guests/haiku/cap/rsync.rb +19 -0
  134. data/plugins/guests/haiku/plugin.rb +15 -0
  135. data/plugins/guests/linux/cap/change_host_name.rb +46 -0
  136. data/plugins/guests/linux/cap/halt.rb +9 -1
  137. data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +25 -34
  138. data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +10 -11
  139. data/plugins/guests/linux/cap/persist_mount_shared_folder.rb +74 -0
  140. data/plugins/guests/linux/cap/reboot.rb +36 -7
  141. data/plugins/guests/linux/plugin.rb +10 -0
  142. data/plugins/guests/omnios/cap/change_host_name.rb +10 -16
  143. data/plugins/guests/openbsd/cap/change_host_name.rb +10 -6
  144. data/plugins/guests/openwrt/cap/change_host_name.rb +19 -0
  145. data/plugins/guests/openwrt/cap/halt.rb +16 -0
  146. data/plugins/guests/openwrt/cap/insert_public_key.rb +20 -0
  147. data/plugins/guests/openwrt/cap/remove_public_key.rb +22 -0
  148. data/plugins/guests/openwrt/cap/rsync.rb +35 -0
  149. data/plugins/guests/openwrt/guest.rb +23 -0
  150. data/plugins/guests/openwrt/plugin.rb +61 -0
  151. data/plugins/guests/photon/cap/change_host_name.rb +9 -15
  152. data/plugins/guests/pld/cap/change_host_name.rb +11 -17
  153. data/plugins/guests/redhat/cap/change_host_name.rb +14 -5
  154. data/plugins/guests/redhat/cap/flavor.rb +3 -1
  155. data/plugins/guests/redhat/cap/smb.rb +20 -0
  156. data/plugins/guests/redhat/plugin.rb +5 -0
  157. data/plugins/guests/slackware/cap/change_host_name.rb +11 -17
  158. data/plugins/guests/solaris11/plugin.rb +5 -0
  159. data/plugins/guests/suse/cap/change_host_name.rb +31 -9
  160. data/plugins/guests/windows/cap/public_key.rb +3 -3
  161. data/plugins/guests/windows/cap/reboot.rb +10 -5
  162. data/plugins/hosts/darwin/cap/fs_iso.rb +49 -0
  163. data/plugins/hosts/darwin/plugin.rb +10 -0
  164. data/plugins/hosts/linux/cap/fs_iso.rb +49 -0
  165. data/plugins/hosts/linux/cap/nfs.rb +1 -0
  166. data/plugins/hosts/linux/cap/rdp.rb +1 -1
  167. data/plugins/hosts/linux/plugin.rb +10 -0
  168. data/plugins/hosts/windows/cap/fs_iso.rb +48 -0
  169. data/plugins/hosts/windows/cap/rdp.rb +1 -1
  170. data/plugins/hosts/windows/plugin.rb +15 -0
  171. data/plugins/kernel_v2/config/cloud_init.rb +133 -0
  172. data/plugins/kernel_v2/config/disk.rb +67 -14
  173. data/plugins/kernel_v2/config/ssh_connect.rb +24 -0
  174. data/plugins/kernel_v2/config/vm.rb +155 -21
  175. data/plugins/kernel_v2/config/vm_provisioner.rb +13 -2
  176. data/plugins/kernel_v2/config/vm_trigger.rb +6 -5
  177. data/plugins/providers/docker/action.rb +8 -17
  178. data/plugins/providers/docker/action/forwarded_ports.rb +2 -0
  179. data/plugins/providers/docker/action/prepare_forwarded_port_collision_params.rb +61 -0
  180. data/plugins/providers/docker/cap/has_communicator.rb +11 -0
  181. data/plugins/providers/docker/communicator.rb +1 -1
  182. data/plugins/providers/docker/driver.rb +58 -7
  183. data/plugins/providers/docker/plugin.rb +5 -0
  184. data/plugins/providers/hyperv/action.rb +3 -1
  185. data/plugins/providers/hyperv/action/configure.rb +8 -0
  186. data/plugins/providers/hyperv/action/export.rb +4 -2
  187. data/plugins/providers/hyperv/cap/cleanup_disks.rb +54 -0
  188. data/plugins/providers/hyperv/cap/configure_disks.rb +200 -0
  189. data/plugins/providers/hyperv/cap/validate_disk_ext.rb +34 -0
  190. data/plugins/providers/hyperv/config.rb +5 -0
  191. data/plugins/providers/hyperv/driver.rb +90 -9
  192. data/plugins/providers/hyperv/plugin.rb +25 -0
  193. data/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +28 -0
  194. data/plugins/providers/hyperv/scripts/dismount_vhd.ps1 +13 -0
  195. data/plugins/providers/hyperv/scripts/get_vhd.ps1 +16 -0
  196. data/plugins/providers/hyperv/scripts/get_vm_status.ps1 +1 -1
  197. data/plugins/providers/hyperv/scripts/list_hdds.ps1 +17 -0
  198. data/plugins/providers/hyperv/scripts/new_vhd.ps1 +31 -0
  199. data/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 +25 -0
  200. data/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 +18 -0
  201. data/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 +24 -0
  202. data/plugins/providers/hyperv/scripts/set_vm_integration_services.ps1 +3 -3
  203. data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +14 -6
  204. data/plugins/providers/virtualbox/action.rb +13 -1
  205. data/plugins/providers/virtualbox/action/export.rb +4 -2
  206. data/plugins/providers/virtualbox/action/forward_ports.rb +2 -2
  207. data/plugins/providers/virtualbox/action/import.rb +8 -4
  208. data/plugins/providers/virtualbox/action/network.rb +12 -5
  209. data/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb +4 -2
  210. data/plugins/providers/virtualbox/action/snapshot_delete.rb +4 -2
  211. data/plugins/providers/virtualbox/action/snapshot_restore.rb +4 -2
  212. data/plugins/providers/virtualbox/cap/cleanup_disks.rb +85 -0
  213. data/plugins/providers/virtualbox/cap/configure_disks.rb +440 -0
  214. data/plugins/providers/virtualbox/cap/mount_options.rb +40 -0
  215. data/plugins/providers/virtualbox/cap/validate_disk_ext.rb +34 -0
  216. data/plugins/providers/virtualbox/driver/base.rb +15 -0
  217. data/plugins/providers/virtualbox/driver/meta.rb +16 -2
  218. data/plugins/providers/virtualbox/driver/version_5_0.rb +217 -2
  219. data/plugins/providers/virtualbox/driver/version_6_1.rb +23 -0
  220. data/plugins/providers/virtualbox/model/storage_controller.rb +135 -0
  221. data/plugins/providers/virtualbox/model/storage_controller_array.rb +98 -0
  222. data/plugins/providers/virtualbox/plugin.rb +42 -0
  223. data/plugins/providers/virtualbox/provider.rb +2 -1
  224. data/plugins/providers/virtualbox/synced_folder.rb +1 -0
  225. data/plugins/provisioners/ansible/cap/guest/alpine/ansible_install.rb +44 -0
  226. data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +1 -1
  227. data/plugins/provisioners/ansible/plugin.rb +5 -0
  228. data/plugins/provisioners/ansible/provisioner/base.rb +1 -1
  229. data/plugins/provisioners/container/client.rb +203 -0
  230. data/plugins/provisioners/container/config.rb +83 -0
  231. data/plugins/provisioners/container/installer.rb +13 -0
  232. data/plugins/provisioners/container/plugin.rb +23 -0
  233. data/plugins/provisioners/container/provisioner.rb +28 -0
  234. data/plugins/provisioners/docker/cap/{redhat → centos}/docker_install.rb +10 -7
  235. data/plugins/provisioners/docker/cap/centos/docker_start_service.rb +24 -0
  236. data/plugins/provisioners/docker/client.rb +4 -175
  237. data/plugins/provisioners/docker/config.rb +2 -72
  238. data/plugins/provisioners/docker/installer.rb +3 -5
  239. data/plugins/provisioners/docker/plugin.rb +6 -6
  240. data/plugins/provisioners/docker/provisioner.rb +4 -10
  241. data/plugins/provisioners/podman/cap/centos/podman_install.rb +35 -0
  242. data/plugins/provisioners/podman/cap/linux/podman_installed.rb +13 -0
  243. data/plugins/provisioners/podman/cap/redhat/podman_install.rb +26 -0
  244. data/plugins/provisioners/podman/client.rb +12 -0
  245. data/plugins/provisioners/podman/config.rb +28 -0
  246. data/plugins/provisioners/podman/installer.rb +33 -0
  247. data/plugins/provisioners/podman/plugin.rb +38 -0
  248. data/plugins/provisioners/podman/provisioner.rb +52 -0
  249. data/plugins/provisioners/salt/bootstrap-salt.sh +7 -4
  250. data/plugins/provisioners/salt/provisioner.rb +4 -0
  251. data/plugins/provisioners/shell/config.rb +1 -6
  252. data/plugins/provisioners/shell/provisioner.rb +61 -26
  253. data/plugins/synced_folders/nfs/synced_folder.rb +3 -1
  254. data/plugins/synced_folders/smb/cap/default_fstab_modification.rb +11 -0
  255. data/plugins/synced_folders/smb/cap/mount_options.rb +56 -0
  256. data/plugins/synced_folders/smb/plugin.rb +20 -0
  257. data/plugins/synced_folders/smb/synced_folder.rb +2 -2
  258. data/plugins/synced_folders/unix_mount_helpers.rb +14 -0
  259. data/scripts/website_push_www.sh +1 -1
  260. data/templates/commands/init/Vagrantfile.min.erb +3 -0
  261. data/templates/guests/arch/{network_dhcp.erb → default_network/network_dhcp.erb} +0 -0
  262. data/templates/guests/arch/{network_static.erb → default_network/network_static.erb} +0 -0
  263. data/templates/guests/arch/{network_static6.erb → default_network/network_static6.erb} +0 -0
  264. data/templates/guests/arch/systemd_networkd/network_dhcp.erb +6 -0
  265. data/templates/guests/arch/systemd_networkd/network_static.erb +9 -0
  266. data/templates/guests/arch/systemd_networkd/network_static6.erb +9 -0
  267. data/templates/guests/linux/etc_fstab.erb +6 -0
  268. data/templates/guests/nixos/network.erb +5 -6
  269. data/templates/locales/en.yml +221 -5
  270. data/templates/locales/providers_docker.yml +4 -0
  271. data/templates/nfs/exports_darwin.erb +1 -1
  272. data/vagrant.gemspec +14 -20
  273. data/version.txt +1 -1
  274. metadata +5092 -8978
  275. data/lib/vagrant/action/builtin/after_trigger.rb +0 -31
  276. data/lib/vagrant/action/builtin/before_trigger.rb +0 -28
  277. data/plugins/commands/login/client.rb +0 -253
  278. data/plugins/commands/login/command.rb +0 -137
  279. data/plugins/commands/login/errors.rb +0 -24
  280. data/plugins/commands/login/locales/en.yml +0 -49
  281. data/plugins/provisioners/docker/cap/redhat/docker_start_service.rb +0 -16
  282. data/scripts/website_push_docs.sh +0 -40
@@ -8,6 +8,7 @@ module VagrantPlugins
8
8
  def execute
9
9
  options = {}
10
10
  options[:force] = false
11
+ options[:force_halt] = true
11
12
 
12
13
  opts = OptionParser.new do |o|
13
14
  o.banner = "Usage: vagrant destroy [options] [name|id]"
@@ -23,6 +24,10 @@ module VagrantPlugins
23
24
  "Enable or disable parallelism if provider supports it (automatically enables force)") do |p|
24
25
  options[:parallel] = p
25
26
  end
27
+
28
+ o.on("-g", "--graceful", "Gracefully poweroff of VM") do |f|
29
+ options[:force_halt] = false
30
+ end
26
31
  end
27
32
 
28
33
  # Parse the options
@@ -46,13 +51,12 @@ module VagrantPlugins
46
51
  # gather states to be checked after destroy
47
52
  init_states[vm.name] = vm.state.id
48
53
  machines << vm
49
-
50
- batch.action(vm, :destroy, force_confirm_destroy: options[:force])
54
+ batch.action(vm, :destroy, force_confirm_destroy: options[:force], force_halt: options[:force_halt])
51
55
  end
52
56
  end
53
57
 
54
58
  machines.each do |m|
55
- if m.state.id == init_states[m.name]
59
+ if init_states[m.name] != :not_created && m.state.id == init_states[m.name]
56
60
  declined += 1
57
61
  end
58
62
  end
@@ -60,10 +64,6 @@ module VagrantPlugins
60
64
  # Nothing was declined
61
65
  return 0 if declined == 0
62
66
 
63
- # Everything was declined, and all states are `not_created`
64
- return 0 if declined == machines.length &&
65
- declined == init_states.values.count(:not_created)
66
-
67
67
  # Everything was declined, state was not changed
68
68
  return 1 if declined == machines.length
69
69
 
@@ -2,9 +2,6 @@ require "vagrant"
2
2
 
3
3
  module VagrantPlugins
4
4
  module LoginCommand
5
- autoload :Client, File.expand_path("../client", __FILE__)
6
- autoload :Errors, File.expand_path("../errors", __FILE__)
7
-
8
5
  class Plugin < Vagrant.plugin("2")
9
6
  name "vagrant-login"
10
7
  description <<-DESC
@@ -13,18 +10,8 @@ module VagrantPlugins
13
10
 
14
11
  command(:login) do
15
12
  require File.expand_path("../../cloud/auth/login", __FILE__)
16
- init!
17
13
  VagrantPlugins::CloudCommand::AuthCommand::Command::Login
18
14
  end
19
-
20
- protected
21
-
22
- def self.init!
23
- return if defined?(@_init)
24
- I18n.load_path << File.expand_path("../../cloud/locales/en.yml", __FILE__)
25
- I18n.reload!
26
- @_init = true
27
- end
28
15
  end
29
16
  end
30
17
  end
@@ -55,7 +55,7 @@ module VagrantPlugins
55
55
  proxy_command: ssh_info[:proxy_command],
56
56
  ssh_command: ssh_info[:ssh_command],
57
57
  forward_env: ssh_info[:forward_env],
58
- config: ssh_info[:config],
58
+ config: ssh_info[:config]
59
59
  }
60
60
 
61
61
  # Render the template and output directly to STDOUT
@@ -20,6 +20,7 @@ module VagrantPlugins
20
20
  module CommunicatorSSH
21
21
  # This class provides communication with the VM via SSH.
22
22
  class Communicator < Vagrant.plugin("2", :communicator)
23
+ READY_COMMAND=""
23
24
  # Marker for start of PTY enabled command output
24
25
  PTY_DELIM_START = "bccbb768c119429488cfd109aacea6b5-pty"
25
26
  # Marker for end of PTY enabled command output
@@ -65,7 +66,7 @@ module VagrantPlugins
65
66
  while true
66
67
  ssh_info = @machine.ssh_info
67
68
  break if ssh_info
68
- sleep 0.5
69
+ sleep(0.5)
69
70
  end
70
71
 
71
72
  # Got it! Let the user know what we're connecting to.
@@ -155,7 +156,7 @@ module VagrantPlugins
155
156
  end
156
157
 
157
158
  # Verify the shell is valid
158
- if execute("", error_check: false) != 0
159
+ if execute(self.class.const_get(:READY_COMMAND), error_check: false) != 0
159
160
  raise Vagrant::Errors::SSHInvalidShell
160
161
  end
161
162
 
@@ -168,6 +169,7 @@ module VagrantPlugins
168
169
 
169
170
  # If we used a password, then insert the insecure key
170
171
  ssh_info = @machine.ssh_info
172
+ return if ssh_info.nil?
171
173
  insert = ssh_info[:password] && ssh_info[:private_key_path].empty?
172
174
  ssh_info[:private_key_path].each do |pk|
173
175
  if insecure_key?(pk)
@@ -227,6 +229,7 @@ module VagrantPlugins
227
229
  command: command,
228
230
  shell: nil,
229
231
  sudo: false,
232
+ force_raw: false
230
233
  }.merge(opts || {})
231
234
 
232
235
  opts[:good_exit] = Array(opts[:good_exit])
@@ -238,6 +241,7 @@ module VagrantPlugins
238
241
  shell_opts = {
239
242
  sudo: opts[:sudo],
240
243
  shell: opts[:shell],
244
+ force_raw: opts[:force_raw]
241
245
  }
242
246
 
243
247
  shell_execute(connection, command, **shell_opts) do |type, data|
@@ -303,10 +307,11 @@ module VagrantPlugins
303
307
  scp_connect do |scp|
304
308
  uploader = lambda do |path, remote_dest=nil|
305
309
  if File.directory?(path)
310
+ dest = File.join(to, path.sub(/^#{Regexp.escape(from)}/, ""))
311
+ create_remote_directory(dest)
306
312
  Dir.new(path).each do |entry|
307
313
  next if entry == "." || entry == ".."
308
314
  full_path = File.join(path, entry)
309
- dest = File.join(to, path.sub(/^#{Regexp.escape(from)}/, ""))
310
315
  create_remote_directory(dest)
311
316
  uploader.call(full_path, dest)
312
317
  end
@@ -354,6 +359,11 @@ module VagrantPlugins
354
359
  wait_for_ready(5)
355
360
  end
356
361
 
362
+ def generate_environment_export(env_key, env_value)
363
+ template = machine_config_ssh.export_command_template
364
+ template.sub("%ENV_KEY%", env_key).sub("%ENV_VALUE%", env_value) + "\n"
365
+ end
366
+
357
367
  protected
358
368
 
359
369
  # Opens an SSH connection and yields it to a block.
@@ -398,14 +408,6 @@ module VagrantPlugins
398
408
  auth_methods << "publickey" if ssh_info[:private_key_path]
399
409
  auth_methods << "password" if ssh_info[:password]
400
410
 
401
- # yanked directly from ruby's Net::SSH, but with `none` last
402
- # TODO: Remove this once Vagrant has updated its dependency on Net:SSH
403
- # to be > 4.1.0, which should include this fix.
404
- cipher_array = Net::SSH::Transport::Algorithms::ALGORITHMS[:encryption].dup
405
- if cipher_array.delete("none")
406
- cipher_array.push("none")
407
- end
408
-
409
411
  # Build the options we'll use to initiate the connection via Net::SSH
410
412
  common_connect_opts = {
411
413
  auth_methods: auth_methods,
@@ -416,10 +418,9 @@ module VagrantPlugins
416
418
  verify_host_key: ssh_info[:verify_host_key],
417
419
  password: ssh_info[:password],
418
420
  port: ssh_info[:port],
419
- timeout: 15,
421
+ timeout: ssh_info[:connect_timeout],
420
422
  user_known_hosts_file: [],
421
- verbose: :debug,
422
- encryption: cipher_array,
423
+ verbose: :debug
423
424
  }
424
425
 
425
426
  # Connect to SSH, giving it a few tries
@@ -628,7 +629,7 @@ module VagrantPlugins
628
629
  end
629
630
 
630
631
  # Set the terminal
631
- ch2.send_data generate_environment_export("TERM", "vt100")
632
+ ch2.send_data(generate_environment_export("TERM", "vt100"))
632
633
 
633
634
  # Set SSH_AUTH_SOCK if we are in sudo and forwarding agent.
634
635
  # This is to work around often misconfigured boxes where
@@ -651,7 +652,7 @@ module VagrantPlugins
651
652
  @logger.warn("No SSH_AUTH_SOCK found despite forward_agent being set.")
652
653
  else
653
654
  @logger.info("Setting SSH_AUTH_SOCK remotely: #{auth_socket}")
654
- ch2.send_data generate_environment_export("SSH_AUTH_SOCK", auth_socket)
655
+ ch2.send_data(generate_environment_export("SSH_AUTH_SOCK", auth_socket))
655
656
  end
656
657
  end
657
658
 
@@ -669,11 +670,11 @@ module VagrantPlugins
669
670
  data += "printf #{PTY_DELIM_END}\n"
670
671
  data += "exit $exitcode\n"
671
672
  data = data.force_encoding('ASCII-8BIT')
672
- ch2.send_data data
673
+ ch2.send_data(data)
673
674
  else
674
- ch2.send_data "printf '#{CMD_GARBAGE_MARKER}'\n(>&2 printf '#{CMD_GARBAGE_MARKER}')\n#{command}\n".force_encoding('ASCII-8BIT')
675
+ ch2.send_data("printf '#{CMD_GARBAGE_MARKER}'\n(>&2 printf '#{CMD_GARBAGE_MARKER}')\n#{command}\n".force_encoding('ASCII-8BIT'))
675
676
  # Remember to exit or this channel will hang open
676
- ch2.send_data "exit\n"
677
+ ch2.send_data("exit\n")
677
678
  end
678
679
 
679
680
  # Send eof to let server know we're done
@@ -729,6 +730,11 @@ module VagrantPlugins
729
730
  yield :stdout, data if block_given?
730
731
  end
731
732
 
733
+ if !exit_status
734
+ @logger.debug("Exit status: #{exit_status.inspect}")
735
+ raise Vagrant::Errors::SSHNoExitStatus
736
+ end
737
+
732
738
  # Return the final exit status
733
739
  return exit_status
734
740
  end
@@ -759,11 +765,6 @@ module VagrantPlugins
759
765
  return File.read(path).chomp == source_path.read.chomp
760
766
  end
761
767
 
762
- def generate_environment_export(env_key, env_value)
763
- template = machine_config_ssh.export_command_template
764
- template.sub("%ENV_KEY%", env_key).sub("%ENV_VALUE%", env_value) + "\n"
765
- end
766
-
767
768
  def create_remote_directory(dir)
768
769
  execute("mkdir -p \"#{dir}\"")
769
770
  end
@@ -56,7 +56,7 @@ module VagrantPlugins
56
56
  errors << "winrm.port cannot be nil." if @port.nil?
57
57
  errors << "winrm.guest_port cannot be nil." if @guest_port.nil?
58
58
  errors << "winrm.max_tries cannot be nil." if @max_tries.nil?
59
- errors << "winrm.retry_delay cannot be nil." if @max_tries.nil?
59
+ errors << "winrm.retry_delay cannot be nil." if @retry_delay.nil?
60
60
  errors << "winrm.timeout cannot be nil." if @timeout.nil?
61
61
  errors << "winrm.execution_time_limit cannot be nil." if @execution_time_limit.nil?
62
62
  unless @ssl_peer_verification == true || @ssl_peer_verification == false
@@ -58,7 +58,7 @@ module VagrantPlugins
58
58
  # ports.
59
59
  port = nil
60
60
  if machine.provider.capability?(:forwarded_ports)
61
- machine.provider.capability(:forwarded_ports).each do |host, guest|
61
+ Array(machine.provider.capability(:forwarded_ports)).each do |host, guest|
62
62
  if guest == machine.config.winrm.guest_port
63
63
  port = host
64
64
  break
@@ -19,7 +19,7 @@ module VagrantPlugins
19
19
 
20
20
  # Exit code generated when user is invalid. Can occur
21
21
  # after a hostname update
22
- INVALID_USERID_EXITCODE = -196608
22
+ INVALID_USERID_EXITCODE = -2147024809
23
23
 
24
24
  # These are the exceptions that we retry because they represent
25
25
  # errors that are generally fixed from a retry and don't
@@ -1,27 +1,39 @@
1
1
  require File.expand_path("../../ssh/communicator", __FILE__)
2
2
 
3
+ require 'net/sftp'
4
+
3
5
  module VagrantPlugins
4
6
  module CommunicatorWinSSH
5
7
  # This class provides communication with a Windows VM running
6
8
  # the Windows native port of OpenSSH
7
9
  class Communicator < VagrantPlugins::CommunicatorSSH::Communicator
10
+ # Command to run when checking if connection is ready and working
11
+ READY_COMMAND="dir"
8
12
 
9
13
  def initialize(machine)
10
14
  super
11
15
  @logger = Log4r::Logger.new("vagrant::communication::winssh")
12
16
  end
13
17
 
18
+ # Wrap the shell if required. By default we are using powershell
19
+ # which requires no modification. If cmd is defined as shell, add
20
+ # prefix to start within cmd.exe
21
+ def shell_cmd(opts)
22
+ case opts[:shell].to_s
23
+ when "cmd"
24
+ "cmd.exe /c '#{opts[:command]}'"
25
+ else
26
+ opts[:command]
27
+ end
28
+ end
29
+
14
30
  # Executes the command on an SSH connection within a login shell.
15
31
  def shell_execute(connection, command, **opts)
16
- opts = {
17
- sudo: false,
18
- shell: nil
19
- }.merge(opts)
32
+ opts[:shell] ||= machine_config_ssh.shell
20
33
 
21
- sudo = opts[:sudo]
22
- shell = (opts[:shell] || machine_config_ssh.shell).to_s
34
+ command = shell_cmd(opts.merge(command: command))
23
35
 
24
- @logger.info("Execute: #{command} (sudo=#{sudo.inspect})")
36
+ @logger.info("Execute: #{command} - opts: #{opts}")
25
37
  exit_status = nil
26
38
 
27
39
  # Open the channel so we can execute or command
@@ -31,36 +43,10 @@ module VagrantPlugins
31
43
  stderr_marker_found = false
32
44
  stderr_data_buffer = ''
33
45
 
34
- tfile = Tempfile.new('vagrant-ssh')
35
- remote_ext = shell == "powershell" ? "ps1" : "bat"
36
- remote_name = "#{machine_config_ssh.upload_directory}\\#{File.basename(tfile.path)}.#{remote_ext}"
37
-
38
- if shell == "powershell"
39
- base_cmd = "powershell -File #{remote_name}"
40
- tfile.puts <<-SCRIPT.force_encoding('ASCII-8BIT')
41
- Remove-Item #{remote_name}
42
- Write-Host #{CMD_GARBAGE_MARKER}
43
- [Console]::Error.WriteLine("#{CMD_GARBAGE_MARKER}")
44
- #{command}
45
- SCRIPT
46
- else
47
- base_cmd = remote_name
48
- tfile.puts <<-SCRIPT.force_encoding('ASCII-8BIT')
49
- ECHO OFF
50
- ECHO #{CMD_GARBAGE_MARKER}
51
- ECHO #{CMD_GARBAGE_MARKER} 1>&2
52
- #{command}
53
- SCRIPT
54
- end
55
-
56
- tfile.close
57
- upload(tfile.path, remote_name)
58
- tfile.delete
59
-
60
- base_cmd = shell_cmd(opts.merge(shell: base_cmd))
61
- @logger.debug("Base SSH exec command: #{base_cmd}")
46
+ @logger.debug("Base SSH exec command: #{command}")
47
+ command = "$ProgressPreference = 'SilentlyContinue';Write-Output #{CMD_GARBAGE_MARKER};[Console]::Error.WriteLine('#{CMD_GARBAGE_MARKER}');#{command}"
62
48
 
63
- ch.exec(base_cmd) do |ch2, _|
49
+ ch.exec(command) do |ch2, _|
64
50
  # Setup the channel callbacks so we can get data and exit status
65
51
  ch2.on_data do |ch3, data|
66
52
  # Filter out the clear screen command
@@ -90,14 +76,14 @@ SCRIPT
90
76
  stderr_data_buffer << data
91
77
  marker_index = stderr_data_buffer.index(CMD_GARBAGE_MARKER)
92
78
  if marker_index
93
- marker_found = true
79
+ stderr_marker_found = true
94
80
  stderr_data_buffer.slice!(0, marker_index + CMD_GARBAGE_MARKER.size)
95
81
  data.replace(stderr_data_buffer.lstrip)
96
82
  data_buffer = nil
97
83
  end
98
84
  end
99
85
 
100
- if block_given? && marker_found
86
+ if block_given? && stderr_marker_found && !data.empty?
101
87
  yield :stderr, data
102
88
  end
103
89
  end
@@ -156,6 +142,108 @@ SCRIPT
156
142
  @machine.config.winssh
157
143
  end
158
144
 
145
+ def download(from, to=nil)
146
+ @logger.debug("Downloading: #{from} to #{to}")
147
+
148
+ sftp_connect do |sftp|
149
+ sftp.download!(from, to)
150
+ end
151
+ end
152
+
153
+ # Note: I could not get Net::SFTP to throw a permissions denied error,
154
+ # even when uploading to a directory where I did not have write
155
+ # privileges. I believe this is because Windows SSH sessions are started
156
+ # in an elevated process.
157
+ def upload(from, to)
158
+ to = Vagrant::Util::Platform.unix_windows_path(to)
159
+ @logger.debug("Uploading: #{from} to #{to}")
160
+
161
+ if File.directory?(from)
162
+ if from.end_with?(".")
163
+ @logger.debug("Uploading directory contents of: #{from}")
164
+ from = from.sub(/\.$/, "")
165
+ else
166
+ @logger.debug("Uploading full directory container of: #{from}")
167
+ to = File.join(to, File.basename(File.expand_path(from)))
168
+ end
169
+ end
170
+
171
+ sftp_connect do |sftp|
172
+ uploader = lambda do |path, remote_dest=nil|
173
+ if File.directory?(path)
174
+ Dir.new(path).each do |entry|
175
+ next if entry == "." || entry == ".."
176
+ full_path = File.join(path, entry)
177
+ dest = File.join(to, path.sub(/^#{Regexp.escape(from)}/, ""))
178
+ sftp.mkdir(dest)
179
+ uploader.call(full_path, dest)
180
+ end
181
+ else
182
+ if remote_dest
183
+ dest = File.join(remote_dest, File.basename(path))
184
+ else
185
+ dest = to
186
+ if to.end_with?(File::SEPARATOR)
187
+ dest = File.join(to, File.basename(path))
188
+ end
189
+ end
190
+ @logger.debug("Ensuring remote directory exists for destination upload")
191
+ sftp.mkdir(File.dirname(dest))
192
+ @logger.debug("Uploading file #{path} to remote #{dest}")
193
+ upload_file = File.open(path, "rb")
194
+ begin
195
+ sftp.upload!(upload_file, dest)
196
+ ensure
197
+ upload_file.close
198
+ end
199
+ end
200
+ end
201
+ uploader.call(from)
202
+ end
203
+ end
204
+
205
+ # Opens an SFTP connection and yields it so that you can download and
206
+ # upload files. SFTP works more reliably than SCP on Windows due to
207
+ # issues with shell quoting and escaping.
208
+ def sftp_connect
209
+ # Connect to SFTP and yield the SFTP object
210
+ connect do |connection|
211
+ return yield connection.sftp
212
+ end
213
+ end
214
+
215
+ protected
216
+
217
+ # The WinSSH communicator connection provides isolated modification
218
+ # to the generated connection instances. This modification forces
219
+ # all provided commands to run within powershell
220
+ def connect(**opts)
221
+ connection = nil
222
+ super { |c| connection = c }
223
+
224
+ if !connection.instance_variable_get(:@winssh_patched)
225
+ open_chan = connection.method(:open_channel)
226
+ connection.define_singleton_method(:open_channel) do |*args, &chan_block|
227
+ open_chan.call(*args) do |ch|
228
+ exec = ch.method(:exec)
229
+ ch.define_singleton_method(:exec) do |command, &block|
230
+ command = Base64.strict_encode64(command.encode("UTF-16LE", "UTF-8"))
231
+ command = "powershell -NoLogo -NonInteractive -ExecutionPolicy Bypass " \
232
+ "-NoProfile -EncodedCommand #{command}"
233
+ exec.call(command, &block)
234
+ end
235
+ chan_block.call(ch)
236
+ end
237
+ end
238
+ connection.instance_variable_set(:@winssh_patched, true)
239
+ end
240
+
241
+ if block_given?
242
+ yield connection
243
+ else
244
+ connection
245
+ end
246
+ end
159
247
  end
160
248
  end
161
249
  end