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
@@ -79,11 +79,22 @@ module VagrantPlugins
79
79
  b.use ForwardPorts
80
80
  b.use SetHostname
81
81
  b.use SaneDefaults
82
+ b.use Call, IsEnvSet, :cloud_init do |env, b2|
83
+ if env[:result]
84
+ b2.use CloudInitSetup
85
+ end
86
+ end
87
+ b.use CleanupDisks
82
88
  b.use Disk
83
89
  b.use Customize, "pre-boot"
84
90
  b.use Boot
85
91
  b.use Customize, "post-boot"
86
92
  b.use WaitForCommunicator, [:starting, :running]
93
+ b.use Call, IsEnvSet, :cloud_init do |env, b2|
94
+ if env[:result]
95
+ b2.use CloudInitWait
96
+ end
97
+ end
87
98
  b.use Customize, "post-comm"
88
99
  b.use CheckGuestAdditions
89
100
  end
@@ -105,7 +116,7 @@ module VagrantPlugins
105
116
  b3.use ConfigValidate
106
117
  b3.use ProvisionerCleanup, :before
107
118
  b3.use CheckAccessible
108
- b3.use EnvSet, force_halt: true
119
+ b3.use EnvSet, force_halt: env2[:force_halt]
109
120
  b3.use action_halt
110
121
  b3.use Destroy
111
122
  b3.use CleanMachineFolder
@@ -410,6 +421,7 @@ module VagrantPlugins
410
421
  end
411
422
  end
412
423
 
424
+ b.use EnvSet, cloud_init: true
413
425
  b.use action_start
414
426
  end
415
427
  end
@@ -23,8 +23,10 @@ module VagrantPlugins
23
23
  def export
24
24
  @env[:ui].info I18n.t("vagrant.actions.vm.export.exporting")
25
25
  @env[:machine].provider.driver.export(ovf_path) do |progress|
26
- @env[:ui].clear_line
27
- @env[:ui].report_progress(progress.percent, 100, false)
26
+ @env[:ui].rewriting do |ui|
27
+ ui.clear_line
28
+ ui.report_progress(progress.percent, 100, false)
29
+ end
28
30
  end
29
31
 
30
32
  # Clear the line a final time so the next data can appear
@@ -48,7 +48,7 @@ module VagrantPlugins
48
48
  # bridged networking don't require port-forwarding and establishing
49
49
  # forwarded ports on these attachment types has uncertain behaviour.
50
50
  @env[:ui].detail(I18n.t("vagrant.actions.vm.forward_ports.forwarding_entry",
51
- message_attributes))
51
+ **message_attributes))
52
52
 
53
53
  # Verify we have the network interface to attach to
54
54
  if !interfaces[fp.adapter]
@@ -62,7 +62,7 @@ module VagrantPlugins
62
62
  # so verify that that is the case.
63
63
  if interfaces[fp.adapter][:type] != :nat
64
64
  @env[:ui].detail(I18n.t("vagrant.actions.vm.forward_ports.non_nat",
65
- message_attributes))
65
+ **message_attributes))
66
66
  next
67
67
  end
68
68
 
@@ -19,8 +19,10 @@ module VagrantPlugins
19
19
  env[:ui].info I18n.t("vagrant.actions.vm.clone.creating")
20
20
  env[:machine].id = env[:machine].provider.driver.clonevm(
21
21
  env[:clone_id], env[:clone_snapshot]) do |progress|
22
- env[:ui].clear_line
23
- env[:ui].report_progress(progress, 100, false)
22
+ env[:ui].rewriting do |ui|
23
+ ui.clear_line
24
+ ui.report_progress(progress, 100, false)
25
+ end
24
26
  end
25
27
 
26
28
  # Clear the line one last time since the progress meter doesn't
@@ -51,8 +53,10 @@ module VagrantPlugins
51
53
  # Import the virtual machine
52
54
  ovf_file = env[:machine].box.directory.join("box.ovf").to_s
53
55
  id = env[:machine].provider.driver.import(ovf_file) do |progress|
54
- env[:ui].clear_line
55
- env[:ui].report_progress(progress, 100, false)
56
+ env[:ui].rewriting do |ui|
57
+ ui.clear_line
58
+ ui.report_progress(progress, 100, false)
59
+ end
56
60
  end
57
61
 
58
62
  # Set the machine ID
@@ -255,9 +255,17 @@ module VagrantPlugins
255
255
 
256
256
  # Make sure the type is a symbol
257
257
  options[:type] = options[:type].to_sym
258
-
259
- # Default IP is in the 20-bit private network block for DHCP based networks
260
- options[:ip] = "172.28.128.1" if options[:type] == :dhcp && !options[:ip]
258
+
259
+ if options[:type] == :dhcp && !options[:ip]
260
+ # Try to find a matching device to set the config ip to
261
+ matching_device = hostonly_find_matching_network(options)
262
+ if matching_device
263
+ options[:ip] = matching_device[:ip]
264
+ else
265
+ # Default IP is in the 20-bit private network block for DHCP based networks
266
+ options[:ip] = "172.28.128.1"
267
+ end
268
+ end
261
269
 
262
270
  begin
263
271
  ip = IPAddr.new(options[:ip])
@@ -469,7 +477,7 @@ module VagrantPlugins
469
477
 
470
478
  # This finds a matching host only network for the given configuration.
471
479
  def hostonly_find_matching_network(config)
472
- this_netaddr = network_address(config[:ip], config[:netmask])
480
+ this_netaddr = network_address(config[:ip], config[:netmask]) if config[:ip]
473
481
 
474
482
  @env[:machine].provider.driver.read_host_only_interfaces.each do |interface|
475
483
  return interface if config[:name] && config[:name] == interface[:name]
@@ -515,7 +523,6 @@ module VagrantPlugins
515
523
  # @param [Hash<String>] config hash as returned from hostonly_config
516
524
  def create_dhcp_server_if_necessary(interface, config)
517
525
  existing_dhcp_server = find_matching_dhcp_server(interface)
518
-
519
526
  if existing_dhcp_server
520
527
  if dhcp_server_matches_config?(existing_dhcp_server, config)
521
528
  @logger.debug("DHCP server already properly configured")
@@ -55,8 +55,10 @@ module VagrantPlugins
55
55
  @logger.info("Creating base snapshot for master VM.")
56
56
  env[:machine].provider.driver.create_snapshot(
57
57
  env[:clone_id], name) do |progress|
58
- env[:ui].clear_line
59
- env[:ui].report_progress(progress, 100, false)
58
+ env[:ui].rewriting do |ui|
59
+ ui.clear_line
60
+ ui.report_progress(progress, 100, false)
61
+ end
60
62
  end
61
63
  end
62
64
  end
@@ -12,8 +12,10 @@ module VagrantPlugins
12
12
  name: env[:snapshot_name]))
13
13
  env[:machine].provider.driver.delete_snapshot(
14
14
  env[:machine].id, env[:snapshot_name]) do |progress|
15
- env[:ui].clear_line
16
- env[:ui].report_progress(progress, 100, false)
15
+ env[:ui].rewriting do |ui|
16
+ ui.clear_line
17
+ ui.report_progress(progress, 100, false)
18
+ end
17
19
  end
18
20
 
19
21
  # Clear the line one last time since the progress meter doesn't disappear
@@ -12,8 +12,10 @@ module VagrantPlugins
12
12
  name: env[:snapshot_name]))
13
13
  env[:machine].provider.driver.restore_snapshot(
14
14
  env[:machine].id, env[:snapshot_name]) do |progress|
15
- env[:ui].clear_line
16
- env[:ui].report_progress(progress, 100, false)
15
+ env[:ui].rewriting do |ui|
16
+ ui.clear_line
17
+ ui.report_progress(progress, 100, false)
18
+ end
17
19
  end
18
20
 
19
21
  # Clear the line one last time since the progress meter doesn't disappear
@@ -0,0 +1,85 @@
1
+ require "log4r"
2
+ require "vagrant/util/experimental"
3
+
4
+ module VagrantPlugins
5
+ module ProviderVirtualBox
6
+ module Cap
7
+ module CleanupDisks
8
+ LOGGER = Log4r::Logger.new("vagrant::plugins::virtualbox::cleanup_disks")
9
+
10
+ # @param [Vagrant::Machine] machine
11
+ # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks
12
+ # @param [Hash] disk_meta_file - A hash of all the previously defined disks from the last configure_disk action
13
+ def self.cleanup_disks(machine, defined_disks, disk_meta_file)
14
+ return if disk_meta_file.values.flatten.empty?
15
+
16
+ return if !Vagrant::Util::Experimental.feature_enabled?("disks")
17
+
18
+ handle_cleanup_disk(machine, defined_disks, disk_meta_file["disk"])
19
+ handle_cleanup_dvd(machine, defined_disks, disk_meta_file["dvd"])
20
+ # TODO: Floppy disks
21
+ end
22
+
23
+ protected
24
+
25
+ # @param [Vagrant::Machine] machine
26
+ # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks
27
+ # @param [Array<Hash>] disk_meta - An array of all the previously defined disks from the last configure_disk action
28
+ def self.handle_cleanup_disk(machine, defined_disks, disk_meta)
29
+ raise TypeError, "Expected `Array` but received `#{disk_meta.class}`" if !disk_meta.is_a?(Array)
30
+ storage_controllers = machine.provider.driver.read_storage_controllers
31
+
32
+ primary = storage_controllers.get_primary_attachment
33
+ primary_uuid = primary[:uuid]
34
+
35
+ disk_meta.each do |d|
36
+ dsk = defined_disks.select { |dk| dk.name == d["name"] }
37
+ if !dsk.empty? || d["uuid"] == primary_uuid
38
+ next
39
+ else
40
+ LOGGER.warn("Found disk not in Vagrantfile config: '#{d["name"]}'. Removing disk from guest #{machine.name}")
41
+ machine.ui.warn(I18n.t("vagrant.cap.cleanup_disks.disk_cleanup", name: d["name"]), prefix: true)
42
+
43
+ controller = storage_controllers.get_controller(d["controller"])
44
+ attachment = controller.get_attachment(uuid: d["uuid"])
45
+
46
+ if !attachment
47
+ LOGGER.warn("Disk '#{d["name"]}' not attached to guest, but still exists.")
48
+ else
49
+ machine.provider.driver.remove_disk(controller.name, attachment[:port], attachment[:device])
50
+ end
51
+
52
+ machine.provider.driver.close_medium(d["uuid"])
53
+ end
54
+ end
55
+ end
56
+
57
+ # @param [Vagrant::Machine] machine
58
+ # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_dvds
59
+ # @param [Array<Hash>] dvd_meta - An array of all the previously defined dvds from the last configure_disk action
60
+ def self.handle_cleanup_dvd(machine, defined_dvds, dvd_meta)
61
+ raise TypeError, "Expected `Array` but received `#{dvd_meta.class}`" if !dvd_meta.is_a?(Array)
62
+ dvd_meta.each do |d|
63
+ dsk = defined_dvds.select { |dk| dk.name == d["name"] }
64
+ if !dsk.empty?
65
+ next
66
+ else
67
+ LOGGER.warn("Found dvd not in Vagrantfile config: '#{d["name"]}'. Removing dvd from guest #{machine.name}")
68
+ machine.ui.warn("DVD '#{d["name"]}' no longer exists in Vagrant config. Removing medium from guest...", prefix: true)
69
+
70
+ storage_controllers = machine.provider.driver.read_storage_controllers
71
+ controller = storage_controllers.get_controller(d["controller"])
72
+ attachment = controller.get_attachment(uuid: d["uuid"])
73
+
74
+ if !attachment
75
+ LOGGER.warn("DVD '#{d["name"]}' not attached to guest, but still exists.")
76
+ else
77
+ machine.provider.driver.remove_disk(controller.name, attachment[:port], attachment[:device])
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,440 @@
1
+ require "log4r"
2
+ require "fileutils"
3
+ require "vagrant/util/numeric"
4
+ require "vagrant/util/experimental"
5
+
6
+ module VagrantPlugins
7
+ module ProviderVirtualBox
8
+ module Cap
9
+ module ConfigureDisks
10
+ LOGGER = Log4r::Logger.new("vagrant::plugins::virtualbox::configure_disks")
11
+
12
+ # @param [Vagrant::Machine] machine
13
+ # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks
14
+ # @return [Hash] configured_disks - A hash of all the current configured disks
15
+ def self.configure_disks(machine, defined_disks)
16
+ return {} if defined_disks.empty?
17
+
18
+ return {} if !Vagrant::Util::Experimental.feature_enabled?("disks")
19
+
20
+ machine.ui.info(I18n.t("vagrant.cap.configure_disks.start"))
21
+
22
+ storage_controllers = machine.provider.driver.read_storage_controllers
23
+
24
+ # Check to determine which controller we should attach disks to.
25
+ # If there is only one storage controller attached to the VM, use
26
+ # it. If there are multiple controllers (e.g. IDE/SATA), attach DVDs
27
+ # to the IDE controller and disks to the SATA controller.
28
+ if storage_controllers.size == 1
29
+ controller = storage_controllers.first
30
+
31
+ # The only way you can define up to the controller limit is if
32
+ # exactly one disk is a primary disk, otherwise we need to reserve
33
+ # a slot for the primary
34
+ if (defined_disks.any? { |d| d.primary } && defined_disks.size > controller.limit) ||
35
+ defined_disks.size > controller.limit - 1
36
+ raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit,
37
+ limit: controller.limit,
38
+ name: controller.name
39
+ else
40
+ disk_controller = controller
41
+ dvd_controller = controller
42
+ end
43
+ else
44
+ disks_defined = defined_disks.select { |d| d.type == :disk }
45
+ if disks_defined.any?
46
+ disk_controller = storage_controllers.get_primary_controller
47
+
48
+ if (disks_defined.any? { |d| d.primary } && disks_defined.size > disk_controller.limit) ||
49
+ disks_defined.size > disk_controller.limit - 1
50
+ raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit,
51
+ limit: disk_controller.limit,
52
+ name: disk_controller.name
53
+ end
54
+ end
55
+
56
+ dvds_defined = defined_disks.select { |d| d.type == :dvd }
57
+ if dvds_defined.any?
58
+ dvd_controller = storage_controllers.get_dvd_controller
59
+
60
+ if dvds_defined.size > dvd_controller.limit
61
+ raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit,
62
+ limit: dvd_controller.limit,
63
+ name: dvd_controller.name
64
+ end
65
+ end
66
+ end
67
+
68
+ configured_disks = { disk: [], floppy: [], dvd: [] }
69
+
70
+ defined_disks.each do |disk|
71
+ if disk.type == :disk
72
+ disk_data = handle_configure_disk(machine, disk, disk_controller.name)
73
+ configured_disks[:disk] << disk_data unless disk_data.empty?
74
+ elsif disk.type == :floppy
75
+ # TODO: Write me
76
+ machine.ui.info(I18n.t("vagrant.cap.configure_disks.floppy_not_supported", name: disk.name))
77
+ elsif disk.type == :dvd
78
+ dvd_data = handle_configure_dvd(machine, disk, dvd_controller.name)
79
+ configured_disks[:dvd] << dvd_data unless dvd_data.empty?
80
+ end
81
+ end
82
+
83
+ configured_disks
84
+ end
85
+
86
+ protected
87
+
88
+ # @param [Vagrant::Machine] machine - the current machine
89
+ # @param [Config::Disk] disk - the current disk to configure
90
+ # @param [Array] all_disks - A list of all currently defined disks in VirtualBox
91
+ # @return [Hash] current_disk - Returns the current disk. Returns nil if it doesn't exist
92
+ def self.get_current_disk(machine, disk, all_disks)
93
+ current_disk = nil
94
+ if disk.primary
95
+ storage_controllers = machine.provider.driver.read_storage_controllers
96
+ current_disk = storage_controllers.get_primary_attachment
97
+ else
98
+ current_disk = all_disks.detect { |d| d[:disk_name] == disk.name }
99
+ end
100
+
101
+ current_disk
102
+ end
103
+
104
+ # Handles all disk configs of type `:disk`
105
+ #
106
+ # @param [Vagrant::Machine] machine - the current machine
107
+ # @param [Config::Disk] disk - the current disk to configure
108
+ # @param [String] controller_name - the name of the storage controller to use
109
+ # @return [Hash] - disk_metadata
110
+ def self.handle_configure_disk(machine, disk, controller_name)
111
+ storage_controllers = machine.provider.driver.read_storage_controllers
112
+ controller = storage_controllers.get_controller(controller_name)
113
+ all_disks = controller.attachments
114
+
115
+ disk_metadata = {}
116
+
117
+ # Grab the existing configured disk attached to guest, if it exists
118
+ current_disk = get_current_disk(machine, disk, all_disks)
119
+
120
+ if !current_disk
121
+ # Look for an existing disk that's not been attached but exists
122
+ # inside VirtualBox
123
+ #
124
+ # NOTE: This assumes that if that disk exists and was created by
125
+ # Vagrant, it exists in the same location as the primary disk file.
126
+ # Otherwise Vagrant has no good way to determining if the disk was
127
+ # associated with the guest, since disk names are not unique
128
+ # globally to VirtualBox.
129
+ primary = storage_controllers.get_primary_attachment
130
+ existing_disk = machine.provider.driver.list_hdds.detect do |d|
131
+ File.dirname(d["Location"]) == File.dirname(primary[:location]) &&
132
+ d["Disk Name"] == disk.name
133
+ end
134
+
135
+ if !existing_disk
136
+ # create new disk and attach to guest
137
+ disk_metadata = create_disk(machine, disk, controller)
138
+ else
139
+ # Disk has been created but failed to be attached to guest, so
140
+ # this method recovers that disk from previous failure
141
+ # and attaches it onto the guest
142
+ LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest")
143
+ dsk_info = get_next_port(machine, controller)
144
+ machine.provider.driver.attach_disk(controller.name,
145
+ dsk_info[:port],
146
+ dsk_info[:device],
147
+ "hdd",
148
+ existing_disk["Location"])
149
+
150
+ disk_metadata[:uuid] = existing_disk["UUID"]
151
+ disk_metadata[:port] = dsk_info[:port]
152
+ disk_metadata[:device] = dsk_info[:device]
153
+ disk_metadata[:name] = disk.name
154
+ disk_metadata[:controller] = controller.name
155
+ end
156
+ elsif compare_disk_size(machine, disk, current_disk)
157
+ disk_metadata = resize_disk(machine, disk, current_disk, controller)
158
+ else
159
+ LOGGER.info("No further configuration required for disk '#{disk.name}'")
160
+ disk_metadata[:uuid] = current_disk[:uuid]
161
+ disk_metadata[:port] = current_disk[:port]
162
+ disk_metadata[:device] = current_disk[:device]
163
+
164
+ disk_metadata[:name] = disk.name
165
+ disk_metadata[:controller] = controller.name
166
+ end
167
+
168
+ disk_metadata
169
+ end
170
+
171
+ # Handles all disk configs of type `:dvd`
172
+ #
173
+ # @param [Vagrant::Machine] machine - the current machine
174
+ # @param [Config::Disk] dvd - the current disk to configure
175
+ # @param [String] controller_name - the name of the storage controller to use
176
+ # @return [Hash] - dvd_metadata
177
+ def self.handle_configure_dvd(machine, dvd, controller_name)
178
+ storage_controllers = machine.provider.driver.read_storage_controllers
179
+ controller = storage_controllers.get_controller(controller_name)
180
+
181
+ dvd_metadata = {}
182
+
183
+ dvd_location = File.expand_path(dvd.file)
184
+ dvd_attached = controller.attachments.detect { |a| a[:location] == dvd_location }
185
+
186
+ if dvd_attached
187
+ LOGGER.info("No further configuration required for dvd '#{dvd.name}'")
188
+ dvd_metadata[:name] = dvd.name
189
+ dvd_metadata[:port] = dvd_attached[:port]
190
+ dvd_metadata[:device] = dvd_attached[:device]
191
+ dvd_metadata[:uuid] = dvd_attached[:uuid]
192
+ dvd_metadata[:controller] = controller.name
193
+ else
194
+ LOGGER.warn("DVD '#{dvd.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect dvd to guest")
195
+ dsk_info = get_next_port(machine, controller)
196
+ machine.provider.driver.attach_disk(controller.name,
197
+ dsk_info[:port],
198
+ dsk_info[:device],
199
+ "dvddrive",
200
+ dvd.file)
201
+
202
+ # Refresh the controller information
203
+ storage_controllers = machine.provider.driver.read_storage_controllers
204
+ controller = storage_controllers.get_controller(controller_name)
205
+
206
+ attachment = controller.attachments.detect { |a| a[:port] == dsk_info[:port] &&
207
+ a[:device] == dsk_info[:device] }
208
+
209
+ dvd_metadata[:name] = dvd.name
210
+ dvd_metadata[:port] = dsk_info[:port]
211
+ dvd_metadata[:device] = dsk_info[:device]
212
+ dvd_metadata[:uuid] = attachment[:uuid]
213
+ dvd_metadata[:controller] = controller.name
214
+ end
215
+
216
+ dvd_metadata
217
+ end
218
+
219
+ # Check to see if current disk is configured based on defined_disks
220
+ #
221
+ # @param [Kernel_V2::VagrantConfigDisk] disk_config
222
+ # @param [Hash] defined_disk
223
+ # @return [Boolean]
224
+ def self.compare_disk_size(machine, disk_config, defined_disk)
225
+ requested_disk_size = Vagrant::Util::Numeric.bytes_to_megabytes(disk_config.size)
226
+ defined_disk_size = defined_disk[:capacity].split(" ").first.to_f
227
+
228
+ if defined_disk_size > requested_disk_size
229
+ machine.ui.warn(I18n.t("vagrant.cap.configure_disks.shrink_size_not_supported", name: disk_config.name))
230
+ return false
231
+ elsif defined_disk_size < requested_disk_size
232
+ return true
233
+ else
234
+ return false
235
+ end
236
+ end
237
+
238
+ # Creates and attaches a disk to a machine
239
+ #
240
+ # @param [Vagrant::Machine] machine
241
+ # @param [Kernel_V2::VagrantConfigDisk] disk_config
242
+ # @param [VagrantPlugins::ProviderVirtualBox::Model::StorageController] controller -
243
+ # the storage controller to use
244
+ def self.create_disk(machine, disk_config, controller)
245
+ machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name))
246
+ # NOTE: At the moment, there are no provider specific configs for VirtualBox
247
+ # but we grab it anyway for future use.
248
+ disk_provider_config = disk_config.provider_config[:virtualbox] if disk_config.provider_config
249
+
250
+ guest_info = machine.provider.driver.show_vm_info
251
+ guest_folder = File.dirname(guest_info["CfgFile"])
252
+
253
+ disk_ext = disk_config.disk_ext
254
+ disk_file = File.join(guest_folder, disk_config.name) + ".#{disk_ext}"
255
+
256
+ LOGGER.info("Attempting to create a new disk file '#{disk_file}' of size '#{disk_config.size}' bytes")
257
+
258
+ disk_var = machine.provider.driver.create_disk(disk_file, disk_config.size, disk_ext.upcase)
259
+ dsk_controller_info = get_next_port(machine, controller)
260
+ machine.provider.driver.attach_disk(controller.name,
261
+ dsk_controller_info[:port],
262
+ dsk_controller_info[:device],
263
+ "hdd",
264
+ disk_file)
265
+
266
+ disk_metadata = { uuid: disk_var.split(":").last.strip, name: disk_config.name,
267
+ controller: controller.name, port: dsk_controller_info[:port],
268
+ device: dsk_controller_info[:device] }
269
+
270
+ disk_metadata
271
+ end
272
+
273
+ # Finds the next available port
274
+ #
275
+ # SATA Controller-ImageUUID-0-0 (sub out ImageUUID)
276
+ # - Controller: SATA Controller
277
+ # - Port: 0
278
+ # - Device: 0
279
+ #
280
+ # Note: Virtualbox returns the string above with the port and device info
281
+ # disk_info = key.split("-")
282
+ # port = disk_info[2]
283
+ # device = disk_info[3]
284
+ #
285
+ # @param [Vagrant::Machine] machine
286
+ # @param [VagrantPlugins::ProviderVirtualBox::Model::StorageController] controller -
287
+ # the storage controller to use
288
+ # @return [Hash] dsk_info - The next available port and device on a given controller
289
+ def self.get_next_port(machine, controller)
290
+ dsk_info = {}
291
+
292
+ if controller.devices_per_port == 1
293
+ used_ports = controller.attachments.map { |a| a[:port].to_i }
294
+ next_available_port = ((0..(controller.maxportcount - 1)).to_a - used_ports).first
295
+
296
+ dsk_info[:port] = next_available_port.to_s
297
+ dsk_info[:device] = "0"
298
+ elsif controller.devices_per_port == 2
299
+ # IDE Controllers have primary/secondary devices, so find the first port
300
+ # with an empty device
301
+ (0..(controller.maxportcount - 1)).each do |port|
302
+ # Skip this port if it's full
303
+ port_attachments = controller.attachments.select { |a| a[:port] == port.to_s }
304
+ next if port_attachments.count == controller.devices_per_port
305
+
306
+ dsk_info[:port] = port.to_s
307
+
308
+ # Check for a free device
309
+ if port_attachments.any? { |a| a[:device] == "0" }
310
+ dsk_info[:device] = "1"
311
+ else
312
+ dsk_info[:device] = "0"
313
+ end
314
+
315
+ break if dsk_info[:port]
316
+ end
317
+ else
318
+ raise Vagrant::Errors::VirtualBoxDisksUnsupportedController, controller_name: controller.name
319
+ end
320
+
321
+ if dsk_info[:port].to_s.empty?
322
+ # This likely only occurs if additional disks have been added outside of Vagrant configuration
323
+ LOGGER.warn("There is no more available space to attach disks to for the controller '#{controller}'. Clear up some space on the controller '#{controller}' to attach new disks.")
324
+ raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit,
325
+ limit: controller.limit,
326
+ name: controller.name
327
+ end
328
+
329
+ dsk_info
330
+ end
331
+
332
+ # @param [Vagrant::Machine] machine
333
+ # @param [Config::Disk] disk_config - the current disk to configure
334
+ # @param [Hash] defined_disk - current disk as represented by VirtualBox
335
+ # @param [VagrantPlugins::ProviderVirtualBox::Model::StorageController] controller -
336
+ # the storage controller to use
337
+ # @return [Hash] - disk_metadata
338
+ def self.resize_disk(machine, disk_config, defined_disk, controller)
339
+ machine.ui.detail(I18n.t("vagrant.cap.configure_disks.resize_disk", name: disk_config.name), prefix: true)
340
+
341
+ if defined_disk[:storage_format] == "VMDK"
342
+ LOGGER.warn("Disk type VMDK cannot be resized in VirtualBox. Vagrant will convert disk to VDI format to resize first, and then convert resized disk back to VMDK format")
343
+
344
+ # original disk information in case anything goes wrong during clone/resize
345
+ original_disk = defined_disk
346
+ backup_disk_location = "#{original_disk[:location]}.backup"
347
+
348
+ # clone disk to vdi formatted disk
349
+ vdi_disk_file = machine.provider.driver.vmdk_to_vdi(defined_disk[:location])
350
+ # resize vdi
351
+ machine.provider.driver.resize_disk(vdi_disk_file, disk_config.size.to_i)
352
+
353
+ begin
354
+ # Danger Zone
355
+ # remove and close original volume
356
+ machine.provider.driver.remove_disk(controller.name, defined_disk[:port], defined_disk[:device])
357
+ # Create a backup of the original disk if something goes wrong
358
+ LOGGER.warn("Making a backup of the original disk at #{defined_disk[:location]}")
359
+ FileUtils.mv(defined_disk[:location], backup_disk_location)
360
+
361
+ # we have to close here, otherwise we can't re-clone after
362
+ # resizing the vdi disk
363
+ machine.provider.driver.close_medium(defined_disk[:uuid])
364
+
365
+ # clone back to original vmdk format and attach resized disk
366
+ vmdk_disk_file = machine.provider.driver.vdi_to_vmdk(vdi_disk_file)
367
+ machine.provider.driver.attach_disk(controller.name,
368
+ defined_disk[:port],
369
+ defined_disk[:device],
370
+ "hdd",
371
+ vmdk_disk_file)
372
+ rescue ScriptError, SignalException, StandardError
373
+ LOGGER.warn("Vagrant encountered an error while trying to resize a disk. Vagrant will now attempt to reattach and preserve the original disk...")
374
+ machine.ui.error(I18n.t("vagrant.cap.configure_disks.recovery_from_resize",
375
+ location: original_disk[:location],
376
+ name: machine.name))
377
+ recover_from_resize(machine, defined_disk, backup_disk_location, original_disk, vdi_disk_file, controller)
378
+ raise
379
+ ensure
380
+ # Remove backup disk file if all goes well
381
+ FileUtils.remove(backup_disk_location, force: true)
382
+ end
383
+
384
+ # Remove cloned resized volume format
385
+ machine.provider.driver.close_medium(vdi_disk_file)
386
+
387
+ # Get new updated disk UUID for vagrant disk_meta file
388
+ storage_controllers = machine.provider.driver.read_storage_controllers
389
+ updated_controller = storage_controllers.get_controller(controller.name)
390
+ new_disk_info = updated_controller.attachments.detect { |h| h[:location] == defined_disk[:location] }
391
+
392
+ defined_disk = new_disk_info
393
+ else
394
+ machine.provider.driver.resize_disk(defined_disk[:location], disk_config.size.to_i)
395
+ end
396
+
397
+ disk_metadata = { uuid: defined_disk[:uuid], name: disk_config.name, controller: controller.name,
398
+ port: defined_disk[:port], device: defined_disk[:device] }
399
+
400
+ disk_metadata
401
+ end
402
+
403
+ # Recovery method for when an exception occurs during the process of resizing disks
404
+ #
405
+ # It attempts to move back the backup disk into place, and reattach it to the guest before
406
+ # raising the original error
407
+ #
408
+ # @param [Vagrant::Machine] machine
409
+ # @param [Hash] disk_info - The disk device and port number to attach back to
410
+ # @param [String] backup_disk_location - The place on disk where vagrant made a backup of the original disk being resized
411
+ # @param [Hash] original_disk - The disk information from VirtualBox
412
+ # @param [String] vdi_disk_file - The place on disk where vagrant made a clone of the original disk being resized
413
+ # @param [VagrantPlugins::ProviderVirtualBox::Model::StorageController] controller - the storage controller to use
414
+ def self.recover_from_resize(machine, disk_info, backup_disk_location, original_disk, vdi_disk_file, controller)
415
+ begin
416
+ # move backup to original name
417
+ FileUtils.mv(backup_disk_location, original_disk[:location], force: true)
418
+ # Attach disk
419
+ machine.provider.driver.attach_disk(controller.name,
420
+ disk_info[:port],
421
+ disk_info[:device],
422
+ "hdd",
423
+ original_disk[:location])
424
+
425
+ # Remove cloned disk if still hanging around
426
+ if vdi_disk_file
427
+ machine.provider.driver.close_medium(vdi_disk_file)
428
+ end
429
+
430
+ # We recovered!
431
+ machine.ui.warn(I18n.t("vagrant.cap.configure_disks.recovery_attached_disks"))
432
+ rescue => e
433
+ LOGGER.error("Vagrant encountered an error while trying to recover. It will now show the original error and continue...")
434
+ LOGGER.error(e)
435
+ end
436
+ end
437
+ end
438
+ end
439
+ end
440
+ end