vagrant-unbundled 2.2.6.2 → 2.2.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (287) hide show
  1. checksums.yaml +4 -4
  2. data/.hashibot.hcl +14 -0
  3. data/CHANGELOG.md +213 -2
  4. data/Gemfile +1 -1
  5. data/README.md +9 -51
  6. data/RELEASE.md +1 -1
  7. data/bin/vagrant +23 -0
  8. data/contrib/README.md +1 -0
  9. data/contrib/bash/completion.sh +13 -1
  10. data/contrib/sudoers/linux-suse +2 -2
  11. data/contrib/zsh/_vagrant +738 -0
  12. data/contrib/zsh/generate_zsh_completion.rb +165 -0
  13. data/lib/vagrant.rb +25 -4
  14. data/lib/vagrant/action.rb +8 -0
  15. data/lib/vagrant/action/builder.rb +184 -38
  16. data/lib/vagrant/action/builtin/box_add.rb +20 -8
  17. data/lib/vagrant/action/builtin/box_check_outdated.rb +12 -15
  18. data/lib/vagrant/action/builtin/cleanup_disks.rb +56 -0
  19. data/lib/vagrant/action/builtin/cloud_init_setup.rb +122 -0
  20. data/lib/vagrant/action/builtin/cloud_init_wait.rb +30 -0
  21. data/lib/vagrant/action/builtin/delayed.rb +26 -0
  22. data/lib/vagrant/action/builtin/disk.rb +52 -0
  23. data/lib/vagrant/action/builtin/handle_box.rb +3 -1
  24. data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +28 -9
  25. data/lib/vagrant/action/builtin/has_provisioner.rb +36 -0
  26. data/lib/vagrant/action/builtin/mixin_provisioners.rb +20 -1
  27. data/lib/vagrant/action/builtin/mixin_synced_folders.rb +20 -21
  28. data/lib/vagrant/action/builtin/set_hostname.rb +5 -1
  29. data/lib/vagrant/action/builtin/ssh_run.rb +21 -3
  30. data/lib/vagrant/action/builtin/synced_folders.rb +16 -0
  31. data/lib/vagrant/action/builtin/trigger.rb +37 -0
  32. data/lib/vagrant/action/hook.rb +76 -23
  33. data/lib/vagrant/action/runner.rb +12 -27
  34. data/lib/vagrant/action/warden.rb +28 -22
  35. data/lib/vagrant/box.rb +11 -4
  36. data/lib/vagrant/box_collection.rb +1 -1
  37. data/lib/vagrant/box_metadata.rb +17 -3
  38. data/lib/vagrant/bundler.rb +298 -59
  39. data/lib/vagrant/cli.rb +4 -2
  40. data/lib/vagrant/errors.rb +61 -1
  41. data/lib/vagrant/machine.rb +64 -11
  42. data/lib/vagrant/machine_index.rb +28 -1
  43. data/lib/vagrant/plugin/manager.rb +25 -14
  44. data/lib/vagrant/plugin/v2/command.rb +7 -2
  45. data/lib/vagrant/plugin/v2/components.rb +6 -0
  46. data/lib/vagrant/plugin/v2/manager.rb +67 -0
  47. data/lib/vagrant/plugin/v2/plugin.rb +13 -0
  48. data/lib/vagrant/plugin/v2/synced_folder.rb +50 -0
  49. data/lib/vagrant/plugin/v2/trigger.rb +64 -25
  50. data/lib/vagrant/shared_helpers.rb +36 -0
  51. data/lib/vagrant/ui.rb +51 -5
  52. data/lib/vagrant/util.rb +1 -0
  53. data/lib/vagrant/util/ansi_escape_code_remover.rb +1 -1
  54. data/lib/vagrant/util/caps.rb +48 -0
  55. data/lib/vagrant/util/credential_scrubber.rb +1 -1
  56. data/lib/vagrant/util/curl_helper.rb +8 -5
  57. data/lib/vagrant/util/directory.rb +19 -0
  58. data/lib/vagrant/util/downloader.rb +10 -5
  59. data/lib/vagrant/util/file_checksum.rb +6 -2
  60. data/lib/vagrant/util/guest_hosts.rb +68 -0
  61. data/lib/vagrant/util/guest_inspection.rb +9 -1
  62. data/lib/vagrant/util/install_cli_autocomplete.rb +118 -0
  63. data/lib/vagrant/util/io.rb +7 -27
  64. data/lib/vagrant/util/ipv4_interfaces.rb +15 -0
  65. data/lib/vagrant/util/is_port_open.rb +8 -20
  66. data/lib/vagrant/util/map_command_options.rb +33 -0
  67. data/lib/vagrant/util/mime.rb +92 -0
  68. data/lib/vagrant/util/network_ip.rb +11 -1
  69. data/lib/vagrant/util/numeric.rb +69 -0
  70. data/lib/vagrant/util/platform.rb +10 -2
  71. data/lib/vagrant/util/powershell.rb +1 -1
  72. data/lib/vagrant/util/subprocess.rb +9 -1
  73. data/lib/vagrant/util/template_renderer.rb +2 -2
  74. data/lib/vagrant/util/uploader.rb +7 -4
  75. data/lib/vagrant/vagrantfile.rb +1 -1
  76. data/plugins/commands/autocomplete/command/install.rb +49 -0
  77. data/plugins/commands/autocomplete/command/root.rb +64 -0
  78. data/plugins/commands/autocomplete/plugin.rb +18 -0
  79. data/plugins/commands/box/command/outdated.rb +14 -2
  80. data/plugins/commands/cap/command.rb +5 -1
  81. data/plugins/commands/cloud/auth/login.rb +20 -23
  82. data/plugins/commands/cloud/auth/logout.rb +2 -10
  83. data/plugins/commands/cloud/auth/middleware/add_downloader_authentication.rb +57 -0
  84. data/plugins/commands/cloud/auth/whoami.rb +18 -20
  85. data/plugins/commands/cloud/box/create.rb +33 -29
  86. data/plugins/commands/cloud/box/delete.rb +30 -24
  87. data/plugins/commands/cloud/box/show.rb +41 -31
  88. data/plugins/commands/cloud/box/update.rb +34 -26
  89. data/plugins/commands/cloud/client/client.rb +50 -81
  90. data/plugins/commands/cloud/list.rb +3 -4
  91. data/plugins/commands/cloud/locales/en.yml +10 -10
  92. data/plugins/commands/cloud/plugin.rb +10 -0
  93. data/plugins/commands/cloud/provider/create.rb +38 -28
  94. data/plugins/commands/cloud/provider/delete.rb +39 -29
  95. data/plugins/commands/cloud/provider/update.rb +37 -28
  96. data/plugins/commands/cloud/provider/upload.rb +44 -34
  97. data/plugins/commands/cloud/publish.rb +185 -108
  98. data/plugins/commands/cloud/search.rb +34 -21
  99. data/plugins/commands/cloud/util.rb +266 -162
  100. data/plugins/commands/cloud/version/create.rb +33 -28
  101. data/plugins/commands/cloud/version/delete.rb +35 -28
  102. data/plugins/commands/cloud/version/release.rb +35 -29
  103. data/plugins/commands/cloud/version/revoke.rb +36 -29
  104. data/plugins/commands/cloud/version/update.rb +29 -25
  105. data/plugins/commands/destroy/command.rb +6 -2
  106. data/plugins/commands/login/plugin.rb +0 -13
  107. data/plugins/commands/snapshot/command/save.rb +13 -8
  108. data/plugins/commands/ssh_config/command.rb +1 -1
  109. data/plugins/communicators/ssh/communicator.rb +25 -24
  110. data/plugins/communicators/winrm/config.rb +1 -1
  111. data/plugins/communicators/winrm/helper.rb +1 -1
  112. data/plugins/communicators/winrm/shell.rb +1 -1
  113. data/plugins/communicators/winssh/communicator.rb +126 -38
  114. data/plugins/communicators/winssh/config.rb +3 -7
  115. data/plugins/guests/alpine/cap/change_host_name.rb +10 -11
  116. data/plugins/guests/alpine/cap/rsync.rb +1 -1
  117. data/plugins/guests/alpine/plugin.rb +16 -0
  118. data/plugins/guests/alt/cap/change_host_name.rb +40 -53
  119. data/plugins/guests/arch/cap/change_host_name.rb +5 -14
  120. data/plugins/guests/arch/cap/configure_networks.rb +27 -10
  121. data/plugins/guests/arch/cap/smb.rb +1 -1
  122. data/plugins/guests/atomic/cap/change_host_name.rb +5 -14
  123. data/plugins/guests/centos/cap/flavor.rb +24 -0
  124. data/plugins/guests/centos/guest.rb +9 -0
  125. data/plugins/guests/centos/plugin.rb +20 -0
  126. data/plugins/guests/darwin/cap/change_host_name.rb +10 -6
  127. data/plugins/guests/darwin/cap/darwin_version.rb +40 -0
  128. data/plugins/guests/darwin/cap/mount_smb_shared_folder.rb +1 -1
  129. data/plugins/guests/darwin/cap/mount_vmware_shared_folder.rb +109 -13
  130. data/plugins/guests/darwin/plugin.rb +15 -0
  131. data/plugins/guests/debian/cap/change_host_name.rb +12 -11
  132. data/plugins/guests/debian/cap/configure_networks.rb +14 -6
  133. data/plugins/guests/esxi/cap/public_key.rb +3 -1
  134. data/plugins/guests/freebsd/cap/change_host_name.rb +10 -6
  135. data/plugins/guests/gentoo/cap/change_host_name.rb +14 -22
  136. data/plugins/guests/haiku/cap/rsync.rb +19 -0
  137. data/plugins/guests/haiku/plugin.rb +15 -0
  138. data/plugins/guests/linux/cap/change_host_name.rb +46 -0
  139. data/plugins/guests/linux/cap/halt.rb +9 -1
  140. data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +25 -34
  141. data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +10 -11
  142. data/plugins/guests/linux/cap/persist_mount_shared_folder.rb +75 -0
  143. data/plugins/guests/linux/cap/reboot.rb +53 -0
  144. data/plugins/guests/linux/plugin.rb +20 -0
  145. data/plugins/guests/omnios/cap/change_host_name.rb +10 -16
  146. data/plugins/guests/openbsd/cap/change_host_name.rb +10 -6
  147. data/plugins/guests/photon/cap/change_host_name.rb +9 -15
  148. data/plugins/guests/pld/cap/change_host_name.rb +11 -17
  149. data/plugins/guests/redhat/cap/change_host_name.rb +14 -5
  150. data/plugins/guests/redhat/cap/flavor.rb +3 -1
  151. data/plugins/guests/redhat/cap/nfs_client.rb +2 -2
  152. data/plugins/guests/redhat/cap/smb.rb +20 -0
  153. data/plugins/guests/redhat/plugin.rb +5 -0
  154. data/plugins/guests/slackware/cap/change_host_name.rb +11 -17
  155. data/plugins/guests/solaris11/plugin.rb +5 -0
  156. data/plugins/guests/suse/cap/change_host_name.rb +31 -9
  157. data/plugins/guests/windows/cap/public_key.rb +3 -3
  158. data/plugins/guests/windows/cap/reboot.rb +10 -5
  159. data/plugins/hosts/darwin/cap/fs_iso.rb +49 -0
  160. data/plugins/hosts/darwin/cap/nfs.rb +11 -0
  161. data/plugins/hosts/darwin/plugin.rb +15 -0
  162. data/plugins/hosts/linux/cap/fs_iso.rb +49 -0
  163. data/plugins/hosts/linux/cap/nfs.rb +21 -2
  164. data/plugins/hosts/linux/cap/rdp.rb +1 -1
  165. data/plugins/hosts/linux/plugin.rb +10 -0
  166. data/plugins/hosts/windows/cap/fs_iso.rb +48 -0
  167. data/plugins/hosts/windows/cap/rdp.rb +1 -1
  168. data/plugins/hosts/windows/plugin.rb +15 -0
  169. data/plugins/kernel_v2/config/cloud_init.rb +133 -0
  170. data/plugins/kernel_v2/config/disk.rb +221 -0
  171. data/plugins/kernel_v2/config/ssh_connect.rb +24 -0
  172. data/plugins/kernel_v2/config/vm.rb +230 -15
  173. data/plugins/kernel_v2/config/vm_provisioner.rb +17 -3
  174. data/plugins/kernel_v2/config/vm_trigger.rb +6 -5
  175. data/plugins/providers/docker/action.rb +8 -17
  176. data/plugins/providers/docker/action/forwarded_ports.rb +2 -0
  177. data/plugins/providers/docker/action/prepare_forwarded_port_collision_params.rb +61 -0
  178. data/plugins/providers/docker/cap/has_communicator.rb +11 -0
  179. data/plugins/providers/docker/communicator.rb +1 -1
  180. data/plugins/providers/docker/driver.rb +73 -10
  181. data/plugins/providers/docker/errors.rb +4 -0
  182. data/plugins/providers/docker/executor/local.rb +7 -1
  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 +14 -1
  205. data/plugins/providers/virtualbox/action/clean_machine_folder.rb +10 -1
  206. data/plugins/providers/virtualbox/action/export.rb +4 -2
  207. data/plugins/providers/virtualbox/action/forward_ports.rb +2 -2
  208. data/plugins/providers/virtualbox/action/import.rb +8 -4
  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 +35 -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 +17 -2
  218. data/plugins/providers/virtualbox/driver/version_5_0.rb +217 -2
  219. data/plugins/providers/virtualbox/driver/version_6_1.rb +39 -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 +38 -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/arch/ansible_install.rb +20 -3
  227. data/plugins/provisioners/ansible/cap/guest/debian/ansible_install.rb +4 -5
  228. data/plugins/provisioners/ansible/cap/guest/fedora/ansible_install.rb +2 -2
  229. data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +2 -2
  230. data/plugins/provisioners/ansible/cap/guest/pip/pip.rb +8 -4
  231. data/plugins/provisioners/ansible/cap/guest/redhat/ansible_install.rb +2 -2
  232. data/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb +2 -1
  233. data/plugins/provisioners/ansible/cap/guest/ubuntu/ansible_install.rb +3 -3
  234. data/plugins/provisioners/ansible/plugin.rb +5 -0
  235. data/plugins/provisioners/ansible/provisioner/base.rb +1 -1
  236. data/plugins/provisioners/container/client.rb +203 -0
  237. data/plugins/provisioners/container/config.rb +83 -0
  238. data/plugins/provisioners/container/installer.rb +13 -0
  239. data/plugins/provisioners/container/plugin.rb +23 -0
  240. data/plugins/provisioners/container/provisioner.rb +28 -0
  241. data/plugins/provisioners/docker/cap/{redhat → centos}/docker_install.rb +10 -7
  242. data/plugins/provisioners/docker/cap/centos/docker_start_service.rb +24 -0
  243. data/plugins/provisioners/docker/client.rb +4 -175
  244. data/plugins/provisioners/docker/config.rb +2 -72
  245. data/plugins/provisioners/docker/installer.rb +3 -5
  246. data/plugins/provisioners/docker/plugin.rb +6 -6
  247. data/plugins/provisioners/docker/provisioner.rb +4 -10
  248. data/plugins/provisioners/podman/cap/centos/podman_install.rb +35 -0
  249. data/plugins/provisioners/podman/cap/linux/podman_installed.rb +13 -0
  250. data/plugins/provisioners/podman/cap/redhat/podman_install.rb +26 -0
  251. data/plugins/provisioners/podman/client.rb +12 -0
  252. data/plugins/provisioners/podman/config.rb +28 -0
  253. data/plugins/provisioners/podman/installer.rb +33 -0
  254. data/plugins/provisioners/podman/plugin.rb +38 -0
  255. data/plugins/provisioners/podman/provisioner.rb +52 -0
  256. data/plugins/provisioners/salt/provisioner.rb +4 -0
  257. data/plugins/provisioners/shell/config.rb +1 -6
  258. data/plugins/provisioners/shell/provisioner.rb +61 -26
  259. data/plugins/synced_folders/nfs/synced_folder.rb +3 -1
  260. data/plugins/synced_folders/smb/cap/default_fstab_modification.rb +11 -0
  261. data/plugins/synced_folders/smb/cap/mount_options.rb +56 -0
  262. data/plugins/synced_folders/smb/plugin.rb +20 -0
  263. data/plugins/synced_folders/smb/synced_folder.rb +2 -2
  264. data/plugins/synced_folders/unix_mount_helpers.rb +14 -0
  265. data/scripts/website_push_www.sh +1 -1
  266. data/templates/commands/init/Vagrantfile.erb +1 -1
  267. data/templates/guests/arch/{network_dhcp.erb → default_network/network_dhcp.erb} +0 -0
  268. data/templates/guests/arch/{network_static.erb → default_network/network_static.erb} +0 -0
  269. data/templates/guests/arch/{network_static6.erb → default_network/network_static6.erb} +0 -0
  270. data/templates/guests/arch/systemd_networkd/network_dhcp.erb +6 -0
  271. data/templates/guests/arch/systemd_networkd/network_static.erb +9 -0
  272. data/templates/guests/arch/systemd_networkd/network_static6.erb +9 -0
  273. data/templates/guests/linux/etc_fstab.erb +6 -0
  274. data/templates/locales/en.yml +235 -6
  275. data/templates/locales/providers_docker.yml +6 -0
  276. data/templates/nfs/exports_darwin.erb +7 -0
  277. data/vagrant.gemspec +14 -15
  278. data/version.txt +1 -1
  279. metadata +3577 -3855
  280. data/lib/vagrant/action/builtin/after_trigger.rb +0 -31
  281. data/lib/vagrant/action/builtin/before_trigger.rb +0 -28
  282. data/plugins/commands/login/client.rb +0 -253
  283. data/plugins/commands/login/command.rb +0 -137
  284. data/plugins/commands/login/errors.rb +0 -24
  285. data/plugins/commands/login/locales/en.yml +0 -49
  286. data/plugins/provisioners/docker/cap/redhat/docker_start_service.rb +0 -16
  287. 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,8 +51,7 @@ 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
 
@@ -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
@@ -15,6 +15,9 @@ module VagrantPlugins
15
15
  o.separator "can be restored via `vagrant snapshot restore` at any point in the"
16
16
  o.separator "future to get back to this exact machine state."
17
17
  o.separator ""
18
+ o.separator "If no vm-name is given, Vagrant will take a snapshot of"
19
+ o.separator "the entire environment with the same snapshot name."
20
+ o.separator ""
18
21
  o.separator "Snapshots are useful for experimenting in a machine and being able"
19
22
  o.separator "to rollback quickly."
20
23
 
@@ -31,20 +34,22 @@ module VagrantPlugins
31
34
  help: opts.help.chomp
32
35
  end
33
36
 
34
- # If no snapshot name is given, the backup name is the same as the machine name.
35
- # If there is a name given, we need to remove it and save it as `name`. Otherwise
36
- # `with_target_vms` will treat the snapshot name as a guest name.
37
- if argv.size < 2
38
- name = argv.first
39
- else
40
- name = argv.pop
41
- end
37
+ name = argv.pop
42
38
 
43
39
  with_target_vms(argv) do |vm|
44
40
  if !vm.provider.capability?(:snapshot_list)
45
41
  raise Vagrant::Errors::SnapshotNotSupported
46
42
  end
47
43
 
44
+ # In this case, no vm name was given, and we are iterating over the
45
+ # entire environment. If a vm hasn't been created yet, we can't list
46
+ # its snapshots
47
+ if vm.id.nil?
48
+ @env.ui.warn(I18n.t("vagrant.commands.snapshot.save.vm_not_created",
49
+ name: vm.name))
50
+ next
51
+ end
52
+
48
53
  snapshot_list = vm.provider.capability(:snapshot_list)
49
54
 
50
55
  if !snapshot_list.include? name
@@ -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