vagrant-unbundled 2.2.7.0 → 2.2.16.0

Sign up to get free protection for your applications and to get access to all the features.
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