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.
- checksums.yaml +4 -4
- data/.hashibot.hcl +2 -0
- data/CHANGELOG.md +228 -0
- data/Gemfile +1 -1
- data/README.md +9 -51
- data/RELEASE.md +1 -1
- data/bin/vagrant +50 -1
- data/contrib/README.md +1 -0
- data/contrib/sudoers/linux-suse +2 -2
- data/contrib/zsh/_vagrant +738 -0
- data/contrib/zsh/generate_zsh_completion.rb +165 -0
- data/lib/vagrant.rb +28 -5
- data/lib/vagrant/action.rb +7 -0
- data/lib/vagrant/action/builder.rb +184 -38
- data/lib/vagrant/action/builtin/box_add.rb +24 -8
- data/lib/vagrant/action/builtin/box_check_outdated.rb +2 -1
- data/lib/vagrant/action/builtin/cleanup_disks.rb +56 -0
- data/lib/vagrant/action/builtin/cloud_init_setup.rb +122 -0
- data/lib/vagrant/action/builtin/cloud_init_wait.rb +30 -0
- data/lib/vagrant/action/builtin/delayed.rb +26 -0
- data/lib/vagrant/action/builtin/disk.rb +14 -1
- data/lib/vagrant/action/builtin/handle_box.rb +3 -1
- data/lib/vagrant/action/builtin/handle_forwarded_port_collisions.rb +28 -9
- data/lib/vagrant/action/builtin/has_provisioner.rb +36 -0
- data/lib/vagrant/action/builtin/mixin_provisioners.rb +1 -0
- data/lib/vagrant/action/builtin/mixin_synced_folders.rb +20 -21
- data/lib/vagrant/action/builtin/set_hostname.rb +5 -1
- data/lib/vagrant/action/builtin/synced_folders.rb +16 -0
- data/lib/vagrant/action/builtin/trigger.rb +37 -0
- data/lib/vagrant/action/hook.rb +76 -23
- data/lib/vagrant/action/runner.rb +12 -27
- data/lib/vagrant/action/warden.rb +28 -31
- data/lib/vagrant/box.rb +11 -4
- data/lib/vagrant/box_collection.rb +1 -1
- data/lib/vagrant/bundler.rb +310 -61
- data/lib/vagrant/cli.rb +4 -2
- data/lib/vagrant/environment.rb +1 -0
- data/lib/vagrant/errors.rb +69 -1
- data/lib/vagrant/machine.rb +64 -11
- data/lib/vagrant/machine_index.rb +28 -1
- data/lib/vagrant/patches/net-ssh.rb +186 -0
- data/lib/vagrant/plugin/manager.rb +45 -16
- data/lib/vagrant/plugin/v2/command.rb +7 -2
- data/lib/vagrant/plugin/v2/components.rb +6 -0
- data/lib/vagrant/plugin/v2/manager.rb +67 -0
- data/lib/vagrant/plugin/v2/plugin.rb +13 -0
- data/lib/vagrant/plugin/v2/synced_folder.rb +50 -0
- data/lib/vagrant/plugin/v2/trigger.rb +64 -25
- data/lib/vagrant/shared_helpers.rb +36 -0
- data/lib/vagrant/ui.rb +43 -2
- data/lib/vagrant/util.rb +2 -0
- data/lib/vagrant/util/ansi_escape_code_remover.rb +1 -1
- data/lib/vagrant/util/caps.rb +48 -0
- data/lib/vagrant/util/credential_scrubber.rb +1 -1
- data/lib/vagrant/util/curl_helper.rb +12 -8
- data/lib/vagrant/util/directory.rb +19 -0
- data/lib/vagrant/util/downloader.rb +10 -5
- data/lib/vagrant/util/guest_hosts.rb +68 -0
- data/lib/vagrant/util/guest_inspection.rb +9 -1
- data/lib/vagrant/util/install_cli_autocomplete.rb +118 -0
- data/lib/vagrant/util/io.rb +7 -27
- data/lib/vagrant/util/ipv4_interfaces.rb +15 -0
- data/lib/vagrant/util/is_port_open.rb +8 -19
- data/lib/vagrant/util/map_command_options.rb +33 -0
- data/lib/vagrant/util/mime.rb +92 -0
- data/lib/vagrant/util/network_ip.rb +11 -1
- data/lib/vagrant/util/numeric.rb +28 -0
- data/lib/vagrant/util/platform.rb +10 -2
- data/lib/vagrant/util/powershell.rb +31 -15
- data/lib/vagrant/util/subprocess.rb +9 -1
- data/lib/vagrant/util/template_renderer.rb +2 -2
- data/lib/vagrant/util/uploader.rb +7 -4
- data/lib/vagrant/vagrantfile.rb +2 -2
- data/plugins/commands/autocomplete/command/install.rb +49 -0
- data/plugins/commands/autocomplete/command/root.rb +64 -0
- data/plugins/commands/autocomplete/plugin.rb +18 -0
- data/plugins/commands/cap/command.rb +5 -1
- data/plugins/commands/cloud/auth/login.rb +20 -23
- data/plugins/commands/cloud/auth/logout.rb +2 -10
- data/plugins/commands/cloud/auth/middleware/add_authentication.rb +60 -31
- data/plugins/commands/cloud/auth/middleware/add_downloader_authentication.rb +64 -0
- data/plugins/commands/cloud/auth/whoami.rb +18 -20
- data/plugins/commands/cloud/box/create.rb +33 -29
- data/plugins/commands/cloud/box/delete.rb +30 -24
- data/plugins/commands/cloud/box/show.rb +41 -31
- data/plugins/commands/cloud/box/update.rb +34 -26
- data/plugins/commands/cloud/client/client.rb +55 -79
- data/plugins/commands/cloud/list.rb +3 -4
- data/plugins/commands/cloud/locales/en.yml +15 -11
- data/plugins/commands/cloud/plugin.rb +10 -0
- data/plugins/commands/cloud/provider/create.rb +38 -28
- data/plugins/commands/cloud/provider/delete.rb +39 -29
- data/plugins/commands/cloud/provider/update.rb +37 -28
- data/plugins/commands/cloud/provider/upload.rb +53 -33
- data/plugins/commands/cloud/publish.rb +193 -106
- data/plugins/commands/cloud/search.rb +34 -21
- data/plugins/commands/cloud/util.rb +273 -161
- data/plugins/commands/cloud/version/create.rb +33 -28
- data/plugins/commands/cloud/version/delete.rb +35 -28
- data/plugins/commands/cloud/version/release.rb +35 -29
- data/plugins/commands/cloud/version/revoke.rb +36 -29
- data/plugins/commands/cloud/version/update.rb +29 -25
- data/plugins/commands/destroy/command.rb +7 -7
- data/plugins/commands/login/plugin.rb +0 -13
- data/plugins/commands/ssh_config/command.rb +1 -1
- data/plugins/communicators/ssh/communicator.rb +25 -24
- data/plugins/communicators/winrm/config.rb +1 -1
- data/plugins/communicators/winrm/helper.rb +1 -1
- data/plugins/communicators/winrm/shell.rb +1 -1
- data/plugins/communicators/winssh/communicator.rb +126 -38
- data/plugins/communicators/winssh/config.rb +3 -7
- data/plugins/guests/alpine/cap/change_host_name.rb +10 -11
- data/plugins/guests/alpine/cap/configure_networks.rb +1 -1
- data/plugins/guests/alt/cap/change_host_name.rb +40 -53
- data/plugins/guests/arch/cap/change_host_name.rb +5 -14
- data/plugins/guests/arch/cap/configure_networks.rb +27 -10
- data/plugins/guests/arch/cap/smb.rb +1 -1
- data/plugins/guests/atomic/cap/change_host_name.rb +5 -14
- data/plugins/guests/centos/cap/flavor.rb +24 -0
- data/plugins/guests/centos/guest.rb +9 -0
- data/plugins/guests/centos/plugin.rb +20 -0
- data/plugins/guests/darwin/cap/change_host_name.rb +10 -6
- data/plugins/guests/darwin/cap/darwin_version.rb +40 -0
- data/plugins/guests/darwin/cap/mount_smb_shared_folder.rb +1 -1
- data/plugins/guests/darwin/cap/mount_vmware_shared_folder.rb +33 -10
- data/plugins/guests/darwin/plugin.rb +15 -0
- data/plugins/guests/debian/cap/change_host_name.rb +12 -11
- data/plugins/guests/debian/cap/configure_networks.rb +14 -6
- data/plugins/guests/esxi/cap/public_key.rb +3 -1
- data/plugins/guests/fedora/guest.rb +4 -4
- data/plugins/guests/freebsd/cap/change_host_name.rb +10 -6
- data/plugins/guests/gentoo/cap/change_host_name.rb +14 -22
- data/plugins/guests/haiku/cap/rsync.rb +19 -0
- data/plugins/guests/haiku/plugin.rb +15 -0
- data/plugins/guests/linux/cap/change_host_name.rb +46 -0
- data/plugins/guests/linux/cap/halt.rb +9 -1
- data/plugins/guests/linux/cap/mount_smb_shared_folder.rb +25 -34
- data/plugins/guests/linux/cap/mount_virtualbox_shared_folder.rb +10 -11
- data/plugins/guests/linux/cap/persist_mount_shared_folder.rb +74 -0
- data/plugins/guests/linux/cap/reboot.rb +36 -7
- data/plugins/guests/linux/plugin.rb +10 -0
- data/plugins/guests/omnios/cap/change_host_name.rb +10 -16
- data/plugins/guests/openbsd/cap/change_host_name.rb +10 -6
- data/plugins/guests/openwrt/cap/change_host_name.rb +19 -0
- data/plugins/guests/openwrt/cap/halt.rb +16 -0
- data/plugins/guests/openwrt/cap/insert_public_key.rb +20 -0
- data/plugins/guests/openwrt/cap/remove_public_key.rb +22 -0
- data/plugins/guests/openwrt/cap/rsync.rb +35 -0
- data/plugins/guests/openwrt/guest.rb +23 -0
- data/plugins/guests/openwrt/plugin.rb +61 -0
- data/plugins/guests/photon/cap/change_host_name.rb +9 -15
- data/plugins/guests/pld/cap/change_host_name.rb +11 -17
- data/plugins/guests/redhat/cap/change_host_name.rb +14 -5
- data/plugins/guests/redhat/cap/flavor.rb +3 -1
- data/plugins/guests/redhat/cap/smb.rb +20 -0
- data/plugins/guests/redhat/plugin.rb +5 -0
- data/plugins/guests/slackware/cap/change_host_name.rb +11 -17
- data/plugins/guests/solaris11/plugin.rb +5 -0
- data/plugins/guests/suse/cap/change_host_name.rb +31 -9
- data/plugins/guests/windows/cap/public_key.rb +3 -3
- data/plugins/guests/windows/cap/reboot.rb +10 -5
- data/plugins/hosts/darwin/cap/fs_iso.rb +49 -0
- data/plugins/hosts/darwin/plugin.rb +10 -0
- data/plugins/hosts/linux/cap/fs_iso.rb +49 -0
- data/plugins/hosts/linux/cap/nfs.rb +1 -0
- data/plugins/hosts/linux/cap/rdp.rb +1 -1
- data/plugins/hosts/linux/plugin.rb +10 -0
- data/plugins/hosts/windows/cap/fs_iso.rb +48 -0
- data/plugins/hosts/windows/cap/rdp.rb +1 -1
- data/plugins/hosts/windows/plugin.rb +15 -0
- data/plugins/kernel_v2/config/cloud_init.rb +133 -0
- data/plugins/kernel_v2/config/disk.rb +67 -14
- data/plugins/kernel_v2/config/ssh_connect.rb +24 -0
- data/plugins/kernel_v2/config/vm.rb +155 -21
- data/plugins/kernel_v2/config/vm_provisioner.rb +13 -2
- data/plugins/kernel_v2/config/vm_trigger.rb +6 -5
- data/plugins/providers/docker/action.rb +8 -17
- data/plugins/providers/docker/action/forwarded_ports.rb +2 -0
- data/plugins/providers/docker/action/prepare_forwarded_port_collision_params.rb +61 -0
- data/plugins/providers/docker/cap/has_communicator.rb +11 -0
- data/plugins/providers/docker/communicator.rb +1 -1
- data/plugins/providers/docker/driver.rb +58 -7
- data/plugins/providers/docker/plugin.rb +5 -0
- data/plugins/providers/hyperv/action.rb +3 -1
- data/plugins/providers/hyperv/action/configure.rb +8 -0
- data/plugins/providers/hyperv/action/export.rb +4 -2
- data/plugins/providers/hyperv/cap/cleanup_disks.rb +54 -0
- data/plugins/providers/hyperv/cap/configure_disks.rb +200 -0
- data/plugins/providers/hyperv/cap/validate_disk_ext.rb +34 -0
- data/plugins/providers/hyperv/config.rb +5 -0
- data/plugins/providers/hyperv/driver.rb +90 -9
- data/plugins/providers/hyperv/plugin.rb +25 -0
- data/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +28 -0
- data/plugins/providers/hyperv/scripts/dismount_vhd.ps1 +13 -0
- data/plugins/providers/hyperv/scripts/get_vhd.ps1 +16 -0
- data/plugins/providers/hyperv/scripts/get_vm_status.ps1 +1 -1
- data/plugins/providers/hyperv/scripts/list_hdds.ps1 +17 -0
- data/plugins/providers/hyperv/scripts/new_vhd.ps1 +31 -0
- data/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 +25 -0
- data/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 +18 -0
- data/plugins/providers/hyperv/scripts/set_enhanced_session_transport_type.ps1 +24 -0
- data/plugins/providers/hyperv/scripts/set_vm_integration_services.ps1 +3 -3
- data/plugins/providers/hyperv/scripts/utils/VagrantVM/VagrantVM.psm1 +14 -6
- data/plugins/providers/virtualbox/action.rb +13 -1
- data/plugins/providers/virtualbox/action/export.rb +4 -2
- data/plugins/providers/virtualbox/action/forward_ports.rb +2 -2
- data/plugins/providers/virtualbox/action/import.rb +8 -4
- data/plugins/providers/virtualbox/action/network.rb +12 -5
- data/plugins/providers/virtualbox/action/prepare_clone_snapshot.rb +4 -2
- data/plugins/providers/virtualbox/action/snapshot_delete.rb +4 -2
- data/plugins/providers/virtualbox/action/snapshot_restore.rb +4 -2
- data/plugins/providers/virtualbox/cap/cleanup_disks.rb +85 -0
- data/plugins/providers/virtualbox/cap/configure_disks.rb +440 -0
- data/plugins/providers/virtualbox/cap/mount_options.rb +40 -0
- data/plugins/providers/virtualbox/cap/validate_disk_ext.rb +34 -0
- data/plugins/providers/virtualbox/driver/base.rb +15 -0
- data/plugins/providers/virtualbox/driver/meta.rb +16 -2
- data/plugins/providers/virtualbox/driver/version_5_0.rb +217 -2
- data/plugins/providers/virtualbox/driver/version_6_1.rb +23 -0
- data/plugins/providers/virtualbox/model/storage_controller.rb +135 -0
- data/plugins/providers/virtualbox/model/storage_controller_array.rb +98 -0
- data/plugins/providers/virtualbox/plugin.rb +42 -0
- data/plugins/providers/virtualbox/provider.rb +2 -1
- data/plugins/providers/virtualbox/synced_folder.rb +1 -0
- data/plugins/provisioners/ansible/cap/guest/alpine/ansible_install.rb +44 -0
- data/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +1 -1
- data/plugins/provisioners/ansible/plugin.rb +5 -0
- data/plugins/provisioners/ansible/provisioner/base.rb +1 -1
- data/plugins/provisioners/container/client.rb +203 -0
- data/plugins/provisioners/container/config.rb +83 -0
- data/plugins/provisioners/container/installer.rb +13 -0
- data/plugins/provisioners/container/plugin.rb +23 -0
- data/plugins/provisioners/container/provisioner.rb +28 -0
- data/plugins/provisioners/docker/cap/{redhat → centos}/docker_install.rb +10 -7
- data/plugins/provisioners/docker/cap/centos/docker_start_service.rb +24 -0
- data/plugins/provisioners/docker/client.rb +4 -175
- data/plugins/provisioners/docker/config.rb +2 -72
- data/plugins/provisioners/docker/installer.rb +3 -5
- data/plugins/provisioners/docker/plugin.rb +6 -6
- data/plugins/provisioners/docker/provisioner.rb +4 -10
- data/plugins/provisioners/podman/cap/centos/podman_install.rb +35 -0
- data/plugins/provisioners/podman/cap/linux/podman_installed.rb +13 -0
- data/plugins/provisioners/podman/cap/redhat/podman_install.rb +26 -0
- data/plugins/provisioners/podman/client.rb +12 -0
- data/plugins/provisioners/podman/config.rb +28 -0
- data/plugins/provisioners/podman/installer.rb +33 -0
- data/plugins/provisioners/podman/plugin.rb +38 -0
- data/plugins/provisioners/podman/provisioner.rb +52 -0
- data/plugins/provisioners/salt/bootstrap-salt.sh +7 -4
- data/plugins/provisioners/salt/provisioner.rb +4 -0
- data/plugins/provisioners/shell/config.rb +1 -6
- data/plugins/provisioners/shell/provisioner.rb +61 -26
- data/plugins/synced_folders/nfs/synced_folder.rb +3 -1
- data/plugins/synced_folders/smb/cap/default_fstab_modification.rb +11 -0
- data/plugins/synced_folders/smb/cap/mount_options.rb +56 -0
- data/plugins/synced_folders/smb/plugin.rb +20 -0
- data/plugins/synced_folders/smb/synced_folder.rb +2 -2
- data/plugins/synced_folders/unix_mount_helpers.rb +14 -0
- data/scripts/website_push_www.sh +1 -1
- data/templates/commands/init/Vagrantfile.min.erb +3 -0
- data/templates/guests/arch/{network_dhcp.erb → default_network/network_dhcp.erb} +0 -0
- data/templates/guests/arch/{network_static.erb → default_network/network_static.erb} +0 -0
- data/templates/guests/arch/{network_static6.erb → default_network/network_static6.erb} +0 -0
- data/templates/guests/arch/systemd_networkd/network_dhcp.erb +6 -0
- data/templates/guests/arch/systemd_networkd/network_static.erb +9 -0
- data/templates/guests/arch/systemd_networkd/network_static6.erb +9 -0
- data/templates/guests/linux/etc_fstab.erb +6 -0
- data/templates/guests/nixos/network.erb +5 -6
- data/templates/locales/en.yml +221 -5
- data/templates/locales/providers_docker.yml +4 -0
- data/templates/nfs/exports_darwin.erb +1 -1
- data/vagrant.gemspec +14 -20
- data/version.txt +1 -1
- metadata +5092 -8978
- data/lib/vagrant/action/builtin/after_trigger.rb +0 -31
- data/lib/vagrant/action/builtin/before_trigger.rb +0 -28
- data/plugins/commands/login/client.rb +0 -253
- data/plugins/commands/login/command.rb +0 -137
- data/plugins/commands/login/errors.rb +0 -24
- data/plugins/commands/login/locales/en.yml +0 -49
- data/plugins/provisioners/docker/cap/redhat/docker_start_service.rb +0 -16
- 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:
|
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].
|
27
|
-
|
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].
|
23
|
-
|
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].
|
55
|
-
|
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
|
-
|
260
|
-
|
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].
|
59
|
-
|
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].
|
16
|
-
|
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].
|
16
|
-
|
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
|