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
@@ -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
@@ -0,0 +1,35 @@
1
+ require_relative "../../../synced_folders/unix_mount_helpers"
2
+
3
+ module VagrantPlugins
4
+ module ProviderVirtualBox
5
+ module Cap
6
+ module MountOptions
7
+ extend VagrantPlugins::SyncedFolder::UnixMountHelpers
8
+
9
+ VB_MOUNT_TYPE = "vboxsf".freeze
10
+
11
+ # Returns mount options for a virtual box synced folder
12
+ #
13
+ # @param [Machine] machine
14
+ # @param [String] name of mount
15
+ # @param [String] path of mount on guest
16
+ # @param [Hash] hash of mount options
17
+ def self.mount_options(machine, name, guest_path, options)
18
+ mount_options = options.fetch(:mount_options, [])
19
+ detected_ids = detect_owner_group_ids(machine, guest_path, mount_options, options)
20
+ mount_uid = detected_ids[:uid]
21
+ mount_gid = detected_ids[:gid]
22
+
23
+ mount_options << "uid=#{mount_uid}"
24
+ mount_options << "gid=#{mount_gid}"
25
+ mount_options = mount_options.join(',')
26
+ return mount_options, mount_uid, mount_gid
27
+ end
28
+
29
+ def self.mount_type(machine)
30
+ return VB_MOUNT_TYPE
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end