From 0d6f12fc3a9a031cc7fe3e178e8931676e5946ee Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 13:41:44 -0700 Subject: [PATCH 01/97] Add capabilities for disk management with Hyper-V --- plugins/providers/hyperv/plugin.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plugins/providers/hyperv/plugin.rb b/plugins/providers/hyperv/plugin.rb index 484bf2cae..a80f9f930 100644 --- a/plugins/providers/hyperv/plugin.rb +++ b/plugins/providers/hyperv/plugin.rb @@ -32,6 +32,26 @@ module VagrantPlugins Cap::SnapshotList end + provider_capability(:virtualbox, :configure_disks) do + require_relative "cap/configure_disks" + Cap::ConfigureDisks + end + + provider_capability(:virtualbox, :cleanup_disks) do + require_relative "cap/cleanup_disks" + Cap::CleanupDisks + end + + provider_capability(:virtualbox, :validate_disk_ext) do + require_relative "cap/validate_disk_ext" + Cap::ValidateDiskExt + end + + provider_capability(:virtualbox, :get_default_disk_ext) do + require_relative "cap/validate_disk_ext" + Cap::ValidateDiskExt + end + protected def self.init! From 9020868a93fc8e542dcc069452c5580fde7fc9ce Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 13:48:38 -0700 Subject: [PATCH 02/97] Add initial files for Hyper-V disk configuration and management --- plugins/providers/hyperv/cap/cleanup_disks.rb | 54 ++++ .../providers/hyperv/cap/configure_disks.rb | 287 ++++++++++++++++++ .../providers/hyperv/cap/validate_disk_ext.rb | 27 ++ .../hyperv/cap/cleanup_disks_test.rb | 42 +++ .../hyperv/cap/configure_disks_test.rb | 41 +++ 5 files changed, 451 insertions(+) create mode 100644 plugins/providers/hyperv/cap/cleanup_disks.rb create mode 100644 plugins/providers/hyperv/cap/configure_disks.rb create mode 100644 plugins/providers/hyperv/cap/validate_disk_ext.rb create mode 100644 test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb create mode 100644 test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb new file mode 100644 index 000000000..00255f2ba --- /dev/null +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -0,0 +1,54 @@ +require "log4r" +require "vagrant/util/experimental" + +module VagrantPlugins + module Hyperv + module Cap + module CleanupDisks + LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::cleanup_disks") + + # @param [Vagrant::Machine] machine + # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks + # @param [Hash] disk_meta_file - A hash of all the previously defined disks from the last configure_disk action + def self.cleanup_disks(machine, defined_disks, disk_meta_file) + return if disk_meta_file.values.flatten.empty? + + return if !Vagrant::Util::Experimental.feature_enabled?("disks") + + handle_cleanup_disk(machine, defined_disks, disk_meta_file["disk"]) + # TODO: Floppy and DVD disks + end + + protected + + # @param [Vagrant::Machine] machine + # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks + # @param [Hash] disk_meta - A hash of all the previously defined disks from the last configure_disk action + def self.handle_cleanup_disk(machine, defined_disks, disk_meta) + vm_info = machine.provider.driver.show_vm_info + primary_disk = vm_info["SATA Controller-ImageUUID-0-0"] + + disk_meta.each do |d| + dsk = defined_disks.select { |dk| dk.name == d["name"] } + if !dsk.empty? || d["uuid"] == primary_disk + next + else + LOGGER.warn("Found disk not in Vagrantfile config: '#{d["name"]}'. Removing disk from guest #{machine.name}") + disk_info = machine.provider.driver.get_port_and_device(d["uuid"]) + + machine.ui.warn("Disk '#{d["name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) + + if disk_info.empty? + LOGGER.warn("Disk '#{d["name"]}' not attached to guest, but still exists.") + else + machine.provider.driver.remove_disk(disk_info[:port], disk_info[:device]) + end + + machine.provider.driver.close_medium(d["uuid"]) + end + end + end + end + end + end +end diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb new file mode 100644 index 000000000..70fd1ab72 --- /dev/null +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -0,0 +1,287 @@ +require "log4r" +require "fileutils" +require "vagrant/util/numeric" +require "vagrant/util/experimental" + +module VagrantPlugins + module HyperV + module Cap + module ConfigureDisks + LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::configure_disks") + + # The max amount of disks that can be attached to a single device in a controller + MAX_DISK_NUMBER = 30.freeze + + # @param [Vagrant::Machine] machine + # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks + # @return [Hash] configured_disks - A hash of all the current configured disks + def self.configure_disks(machine, defined_disks) + return {} if defined_disks.empty? + + return {} if !Vagrant::Util::Experimental.feature_enabled?("disks") + + if defined_disks.size > MAX_DISK_NUMBER + # you can only attach up to 30 disks per controller, INCLUDING the primary disk + raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit + end + + machine.ui.info(I18n.t("vagrant.cap.configure_disks.start")) + + current_disks = machine.provider.driver.list_hdds + + configured_disks = {disk: [], floppy: [], dvd: []} + + defined_disks.each do |disk| + if disk.type == :disk + disk_data = handle_configure_disk(machine, disk, current_disks) + configured_disks[:disk] << disk_data unless disk_data.empty? + elsif disk.type == :floppy + # TODO: Write me + machine.ui.info(I18n.t("vagrant.cap.configure_disks.floppy_not_supported", name: disk.name)) + elsif disk.type == :dvd + # TODO: Write me + machine.ui.info(I18n.t("vagrant.cap.configure_disks.dvd_not_supported", name: disk.name)) + end + end + + configured_disks + end + + protected + + # @param [Vagrant::Machine] machine - the current machine + # @param [Config::Disk] disk - the current disk to configure + # @param [Array] all_disks - A list of all currently defined disks in VirtualBox + # @return [Hash] current_disk - Returns the current disk. Returns nil if it doesn't exist + def self.get_current_disk(machine, disk, all_disks) + current_disk = nil + if disk.primary + # Ensure we grab the proper primary disk + # We can't rely on the order of `all_disks`, as they will not + # always come in port order, but primary is always Port 0 Device 0. + vm_info = machine.provider.driver.show_vm_info + primary_uuid = vm_info["SATA Controller-ImageUUID-0-0"] + + current_disk = all_disks.select { |d| d["UUID"] == primary_uuid }.first + else + current_disk = all_disks.select { |d| d["Disk Name"] == disk.name}.first + end + + current_disk + end + + # Handles all disk configs of type `:disk` + # + # @param [Vagrant::Machine] machine - the current machine + # @param [Config::Disk] disk - the current disk to configure + # @param [Array] all_disks - A list of all currently defined disks in VirtualBox + # @return [Hash] - disk_metadata + def self.handle_configure_disk(machine, disk, all_disks) + disk_metadata = {} + + # Grab the existing configured disk, if it exists + current_disk = get_current_disk(machine, disk, all_disks) + + # Configure current disk + if !current_disk + # create new disk and attach + disk_metadata = create_disk(machine, disk) + elsif compare_disk_size(machine, disk, current_disk) + disk_metadata = resize_disk(machine, disk, current_disk) + else + # TODO: What if it needs to be resized? + + disk_info = machine.provider.driver.get_port_and_device(current_disk["UUID"]) + if disk_info.empty? + LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest") + dsk_info = get_next_port(machine) + machine.provider.driver.attach_disk(dsk_info[:port], + dsk_info[:device], + current_disk["Location"]) + else + LOGGER.info("No further configuration required for disk '#{disk.name}'") + end + + disk_metadata = {uuid: current_disk["UUID"], name: disk.name} + end + + disk_metadata + end + + # Check to see if current disk is configured based on defined_disks + # + # @param [Kernel_V2::VagrantConfigDisk] disk_config + # @param [Hash] defined_disk + # @return [Boolean] + def self.compare_disk_size(machine, disk_config, defined_disk) + requested_disk_size = Vagrant::Util::Numeric.bytes_to_megabytes(disk_config.size) + defined_disk_size = defined_disk["Capacity"].split(" ").first.to_f + + if defined_disk_size > requested_disk_size + machine.ui.warn(I18n.t("vagrant.cap.configure_disks.shrink_size_not_supported", name: disk_config.name)) + return false + elsif defined_disk_size < requested_disk_size + return true + else + return false + end + end + + # Creates and attaches a disk to a machine + # + # @param [Vagrant::Machine] machine + # @param [Kernel_V2::VagrantConfigDisk] disk_config + def self.create_disk(machine, disk_config) + machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name)) + # NOTE: At the moment, there are no provider specific configs for VirtualBox + # but we grab it anyway for future use. + disk_provider_config = disk_config.provider_config[:virtualbox] if disk_config.provider_config + + guest_info = machine.provider.driver.show_vm_info + guest_folder = File.dirname(guest_info["CfgFile"]) + + disk_ext = disk_config.disk_ext + disk_file = File.join(guest_folder, disk_config.name) + ".#{disk_ext}" + + LOGGER.info("Attempting to create a new disk file '#{disk_file}' of size '#{disk_config.size}' bytes") + + disk_var = machine.provider.driver.create_disk(disk_file, disk_config.size, disk_ext.upcase) + disk_metadata = {uuid: disk_var.split(':').last.strip, name: disk_config.name} + + dsk_controller_info = get_next_port(machine) + machine.provider.driver.attach_disk(dsk_controller_info[:port], dsk_controller_info[:device], disk_file) + + disk_metadata + end + + # Finds the next available port + # + # SATA Controller-ImageUUID-0-0 (sub out ImageUUID) + # - Controller: SATA Controller + # - Port: 0 + # - Device: 0 + # + # Note: Virtualbox returns the string above with the port and device info + # disk_info = key.split("-") + # port = disk_info[2] + # device = disk_info[3] + # + # @param [Vagrant::Machine] machine + # @return [Hash] dsk_info - The next available port and device on a given controller + def self.get_next_port(machine) + vm_info = machine.provider.driver.show_vm_info + dsk_info = {device: "0", port: "0"} + + disk_images = vm_info.select { |v| v.include?("ImageUUID") && v.include?("SATA Controller") } + used_ports = disk_images.keys.map { |k| k.split('-') }.map {|v| v[2].to_i} + next_available_port = ((0..(MAX_DISK_NUMBER-1)).to_a - used_ports).first + + dsk_info[:port] = next_available_port.to_s + if dsk_info[:port].empty? + # This likely only occurs if additional disks have been added outside of Vagrant configuration + LOGGER.warn("There are no more available ports to attach disks to for the SATA Controller. Clear up some space on the SATA controller to attach new disks.") + raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit + end + + dsk_info + end + + # @param [Vagrant::Machine] machine + # @param [Config::Disk] disk_config - the current disk to configure + # @param [Hash] defined_disk - current disk as represented by VirtualBox + # @return [Hash] - disk_metadata + def self.resize_disk(machine, disk_config, defined_disk) + machine.ui.detail(I18n.t("vagrant.cap.configure_disks.resize_disk", name: disk_config.name), prefix: true) + + if defined_disk["Storage format"] == "VMDK" + 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") + + # grab disk to be resized port and device number + disk_info = machine.provider.driver.get_port_and_device(defined_disk["UUID"]) + # original disk information in case anything goes wrong during clone/resize + original_disk = defined_disk + backup_disk_location = "#{original_disk["Location"]}.backup" + + # clone disk to vdi formatted disk + vdi_disk_file = machine.provider.driver.vmdk_to_vdi(defined_disk["Location"]) + # resize vdi + machine.provider.driver.resize_disk(vdi_disk_file, disk_config.size.to_i) + + begin + # Danger Zone + + # remove and close original volume + machine.provider.driver.remove_disk(disk_info[:port], disk_info[:device]) + # Create a backup of the original disk if something goes wrong + LOGGER.warn("Making a backup of the original disk at #{defined_disk["Location"]}") + FileUtils.mv(defined_disk["Location"], backup_disk_location) + + # we have to close here, otherwise we can't re-clone after + # resizing the vdi disk + machine.provider.driver.close_medium(defined_disk["UUID"]) + + # clone back to original vmdk format and attach resized disk + vmdk_disk_file = machine.provider.driver.vdi_to_vmdk(vdi_disk_file) + machine.provider.driver.attach_disk(disk_info[:port], disk_info[:device], vmdk_disk_file, "hdd") + rescue ScriptError, SignalException, StandardError + LOGGER.warn("Vagrant encountered an error while trying to resize a disk. Vagrant will now attempt to reattach and preserve the original disk...") + machine.ui.error(I18n.t("vagrant.cap.configure_disks.recovery_from_resize", + location: original_disk["Location"], + name: machine.name)) + recover_from_resize(machine, disk_info, backup_disk_location, original_disk, vdi_disk_file) + + raise + ensure + # Remove backup disk file if all goes well + FileUtils.remove(backup_disk_location, force: true) + end + + # Remove cloned resized volume format + machine.provider.driver.close_medium(vdi_disk_file) + + # Get new updated disk UUID for vagrant disk_meta file + new_disk_info = machine.provider.driver.list_hdds.select { |h| h["Location"] == defined_disk["Location"] }.first + defined_disk = new_disk_info + else + machine.provider.driver.resize_disk(defined_disk["Location"], disk_config.size.to_i) + end + + disk_metadata = {uuid: defined_disk["UUID"], name: disk_config.name} + + disk_metadata + end + + # Recovery method for when an exception occurs during the process of resizing disks + # + # It attempts to move back the backup disk into place, and reattach it to the guest before + # raising the original error + # + # @param [Vagrant::Machine] machine + # @param [Hash] disk_info - The disk device and port number to attach back to + # @param [String] backup_disk_location - The place on disk where vagrant made a backup of the original disk being resized + # @param [Hash] original_disk - The disk information from VirtualBox + # @param [String] vdi_disk_file - The place on disk where vagrant made a clone of the original disk being resized + def self.recover_from_resize(machine, disk_info, backup_disk_location, original_disk, vdi_disk_file) + begin + # move backup to original name + FileUtils.mv(backup_disk_location, original_disk["Location"], force: true) + # Attach disk + machine.provider.driver. + attach_disk(disk_info[:port], disk_info[:device], original_disk["Location"], "hdd") + + # Remove cloned disk if still hanging around + if vdi_disk_file + machine.provider.driver.close_medium(vdi_disk_file) + end + + # We recovered! + machine.ui.warn(I18n.t("vagrant.cap.configure_disks.recovery_attached_disks")) + rescue => e + LOGGER.error("Vagrant encountered an error while trying to recover. It will now show the original error and continue...") + LOGGER.error(e) + end + end + end + end + end +end diff --git a/plugins/providers/hyperv/cap/validate_disk_ext.rb b/plugins/providers/hyperv/cap/validate_disk_ext.rb new file mode 100644 index 000000000..248d7b6a6 --- /dev/null +++ b/plugins/providers/hyperv/cap/validate_disk_ext.rb @@ -0,0 +1,27 @@ +require "log4r" + +module VagrantPlugins + module HyperV + module Cap + module ValidateDiskExt + LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::validate_disk_ext") + + # The default set of disk formats that VirtualBox supports + DEFAULT_DISK_EXT = ["vdi", "vmdk", "vhd"].map(&:freeze).freeze + + # @param [Vagrant::Machine] machine + # @param [String] disk_ext + # @return [Bool] + def self.validate_disk_ext(machine, disk_ext) + DEFAULT_DISK_EXT.include?(disk_ext) + end + + # @param [Vagrant::Machine] machine + # @return [Array] + def self.get_default_disk_ext(machine) + DEFAULT_DISK_EXT + end + end + end + end +end diff --git a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb new file mode 100644 index 000000000..18ec85d7c --- /dev/null +++ b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb @@ -0,0 +1,42 @@ +require_relative "../base" + +require Vagrant.source_root.join("plugins/providers/hyperv/cap/cleanup_disks") + +describe VagrantPlugins::HyperV::Cap::CleanupDisks do + include_context "unit" + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:driver) { double("driver") } + + let(:machine) do + iso_env.machine(iso_env.machine_names[0], :dummy).tap do |m| + allow(m.provider).to receive(:driver).and_return(driver) + allow(m).to receive(:state).and_return(state) + end + end + + let(:state) do + double(:state) + end + + let(:subject) { described_class } + + let(:disk_meta_file) { {disk: [], floppy: [], dvd: []} } + let(:defined_disks) { {} } + + before do + allow(Vagrant::Util::Experimental).to receive(:feature_enabled?).and_return(true) + end + + context "#cleanup_disks" do + end + + context "#handle_cleanup_disk" do + end +end diff --git a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb new file mode 100644 index 000000000..1c076d897 --- /dev/null +++ b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb @@ -0,0 +1,41 @@ +require_relative "../base" + +require Vagrant.source_root.join("plugins/providers/hyperv/cap/configure_disks") + +describe VagrantPlugins::HyperV::Cap::ConfigureDisks do + include_context "unit" + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:driver) { double("driver") } + + let(:machine) do + iso_env.machine(iso_env.machine_names[0], :dummy).tap do |m| + allow(m.provider).to receive(:driver).and_return(driver) + allow(m).to receive(:state).and_return(state) + end + end + + let(:state) do + double(:state) + end + + let(:defined_disks) { [double("disk", name: "vagrant_primary", size: "5GB", primary: true, type: :disk), + double("disk", name: "disk-0", size: "5GB", primary: false, type: :disk), + double("disk", name: "disk-1", size: "5GB", primary: false, type: :disk), + double("disk", name: "disk-2", size: "5GB", primary: false, type: :disk)] } + + let(:subject) { described_class } + + before do + allow(Vagrant::Util::Experimental).to receive(:feature_enabled?).and_return(true) + end + + context "#configure_disks" do + end +end From cf47e7ecafe6082a263f2eeac9441d335755cab1 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 13:53:26 -0700 Subject: [PATCH 03/97] Replace virtualbox cap name with hyperv --- plugins/providers/hyperv/plugin.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/providers/hyperv/plugin.rb b/plugins/providers/hyperv/plugin.rb index a80f9f930..cdf88d7e3 100644 --- a/plugins/providers/hyperv/plugin.rb +++ b/plugins/providers/hyperv/plugin.rb @@ -32,22 +32,22 @@ module VagrantPlugins Cap::SnapshotList end - provider_capability(:virtualbox, :configure_disks) do + provider_capability(:hyperv, :configure_disks) do require_relative "cap/configure_disks" Cap::ConfigureDisks end - provider_capability(:virtualbox, :cleanup_disks) do + provider_capability(:hyperv, :cleanup_disks) do require_relative "cap/cleanup_disks" Cap::CleanupDisks end - provider_capability(:virtualbox, :validate_disk_ext) do + provider_capability(:hyperv, :validate_disk_ext) do require_relative "cap/validate_disk_ext" Cap::ValidateDiskExt end - provider_capability(:virtualbox, :get_default_disk_ext) do + provider_capability(:hyperv, :get_default_disk_ext) do require_relative "cap/validate_disk_ext" Cap::ValidateDiskExt end From 8dfa1affdf28b3fa1dbae94a65afb51954f7cb12 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 14:10:33 -0700 Subject: [PATCH 04/97] Use correct disk extension formats for Hyper-V --- plugins/providers/hyperv/cap/validate_disk_ext.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/cap/validate_disk_ext.rb b/plugins/providers/hyperv/cap/validate_disk_ext.rb index 248d7b6a6..92e467f51 100644 --- a/plugins/providers/hyperv/cap/validate_disk_ext.rb +++ b/plugins/providers/hyperv/cap/validate_disk_ext.rb @@ -6,8 +6,8 @@ module VagrantPlugins module ValidateDiskExt LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::validate_disk_ext") - # The default set of disk formats that VirtualBox supports - DEFAULT_DISK_EXT = ["vdi", "vmdk", "vhd"].map(&:freeze).freeze + # The default set of disk formats that Hyper-V supports + DEFAULT_DISK_EXT = ["vhd", "vhdx"].map(&:freeze).freeze # @param [Vagrant::Machine] machine # @param [String] disk_ext From 2ef9274f9df1267d6eaf8ff84f3a0f798e38300b Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 14:22:12 -0700 Subject: [PATCH 05/97] Remove virtualbox code from cleanup_disks method --- plugins/providers/hyperv/cap/cleanup_disks.rb | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 00255f2ba..87414d3fa 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -25,28 +25,6 @@ module VagrantPlugins # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks # @param [Hash] disk_meta - A hash of all the previously defined disks from the last configure_disk action def self.handle_cleanup_disk(machine, defined_disks, disk_meta) - vm_info = machine.provider.driver.show_vm_info - primary_disk = vm_info["SATA Controller-ImageUUID-0-0"] - - disk_meta.each do |d| - dsk = defined_disks.select { |dk| dk.name == d["name"] } - if !dsk.empty? || d["uuid"] == primary_disk - next - else - LOGGER.warn("Found disk not in Vagrantfile config: '#{d["name"]}'. Removing disk from guest #{machine.name}") - disk_info = machine.provider.driver.get_port_and_device(d["uuid"]) - - machine.ui.warn("Disk '#{d["name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) - - if disk_info.empty? - LOGGER.warn("Disk '#{d["name"]}' not attached to guest, but still exists.") - else - machine.provider.driver.remove_disk(disk_info[:port], disk_info[:device]) - end - - machine.provider.driver.close_medium(d["uuid"]) - end - end end end end From 287b0e5aab0f35c946ea61d4f31c1ec79f1f446c Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 14:32:34 -0700 Subject: [PATCH 06/97] Add comment for implementation --- plugins/providers/hyperv/cap/cleanup_disks.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 87414d3fa..825c159aa 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -25,6 +25,8 @@ module VagrantPlugins # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks # @param [Hash] disk_meta - A hash of all the previously defined disks from the last configure_disk action def self.handle_cleanup_disk(machine, defined_disks, disk_meta) + # Iterate over each disk_meta disk, check if it's still defined in the + # guests config, and if it's no longer there, remove it from the guest end end end From 090959227eb03496ed9b135cc330aa2d202bc2fa Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 15:00:43 -0700 Subject: [PATCH 07/97] More comments for TODO with cleaning up disks in hyper-v --- plugins/providers/hyperv/cap/cleanup_disks.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 825c159aa..bc960b7c7 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -27,6 +27,11 @@ module VagrantPlugins def self.handle_cleanup_disk(machine, defined_disks, disk_meta) # Iterate over each disk_meta disk, check if it's still defined in the # guests config, and if it's no longer there, remove it from the guest + disk_meta.each do |d| + # find d in defined_disk + # if found, continue on + # else, remove the disk + end end end end From 787c8a150a0540aae326cde2b1fac9cd21c30cb7 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 15:11:35 -0700 Subject: [PATCH 08/97] Remove virtualbox code from hyper-v configure_disks file --- .../providers/hyperv/cap/configure_disks.rb | 125 ++---------------- 1 file changed, 8 insertions(+), 117 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 70fd1ab72..c489d68e1 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -10,6 +10,7 @@ module VagrantPlugins LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::configure_disks") # The max amount of disks that can be attached to a single device in a controller + # TODO: Figure out if there's a limit for Hyper-V guests MAX_DISK_NUMBER = 30.freeze # @param [Vagrant::Machine] machine @@ -133,9 +134,11 @@ module VagrantPlugins # @param [Kernel_V2::VagrantConfigDisk] disk_config def self.create_disk(machine, disk_config) machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name)) - # NOTE: At the moment, there are no provider specific configs for VirtualBox + # NOTE: At the moment, there are no provider specific configs for Hyper-V # but we grab it anyway for future use. - disk_provider_config = disk_config.provider_config[:virtualbox] if disk_config.provider_config + disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config + + # TODO: Create and store disk before attaching, if required guest_info = machine.provider.driver.show_vm_info guest_folder = File.dirname(guest_info["CfgFile"]) @@ -154,38 +157,6 @@ module VagrantPlugins disk_metadata end - # Finds the next available port - # - # SATA Controller-ImageUUID-0-0 (sub out ImageUUID) - # - Controller: SATA Controller - # - Port: 0 - # - Device: 0 - # - # Note: Virtualbox returns the string above with the port and device info - # disk_info = key.split("-") - # port = disk_info[2] - # device = disk_info[3] - # - # @param [Vagrant::Machine] machine - # @return [Hash] dsk_info - The next available port and device on a given controller - def self.get_next_port(machine) - vm_info = machine.provider.driver.show_vm_info - dsk_info = {device: "0", port: "0"} - - disk_images = vm_info.select { |v| v.include?("ImageUUID") && v.include?("SATA Controller") } - used_ports = disk_images.keys.map { |k| k.split('-') }.map {|v| v[2].to_i} - next_available_port = ((0..(MAX_DISK_NUMBER-1)).to_a - used_ports).first - - dsk_info[:port] = next_available_port.to_s - if dsk_info[:port].empty? - # This likely only occurs if additional disks have been added outside of Vagrant configuration - LOGGER.warn("There are no more available ports to attach disks to for the SATA Controller. Clear up some space on the SATA controller to attach new disks.") - raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit - end - - dsk_info - end - # @param [Vagrant::Machine] machine # @param [Config::Disk] disk_config - the current disk to configure # @param [Hash] defined_disk - current disk as represented by VirtualBox @@ -193,94 +164,14 @@ module VagrantPlugins def self.resize_disk(machine, disk_config, defined_disk) machine.ui.detail(I18n.t("vagrant.cap.configure_disks.resize_disk", name: disk_config.name), prefix: true) - if defined_disk["Storage format"] == "VMDK" - 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") - - # grab disk to be resized port and device number - disk_info = machine.provider.driver.get_port_and_device(defined_disk["UUID"]) - # original disk information in case anything goes wrong during clone/resize - original_disk = defined_disk - backup_disk_location = "#{original_disk["Location"]}.backup" - - # clone disk to vdi formatted disk - vdi_disk_file = machine.provider.driver.vmdk_to_vdi(defined_disk["Location"]) - # resize vdi - machine.provider.driver.resize_disk(vdi_disk_file, disk_config.size.to_i) - - begin - # Danger Zone - - # remove and close original volume - machine.provider.driver.remove_disk(disk_info[:port], disk_info[:device]) - # Create a backup of the original disk if something goes wrong - LOGGER.warn("Making a backup of the original disk at #{defined_disk["Location"]}") - FileUtils.mv(defined_disk["Location"], backup_disk_location) - - # we have to close here, otherwise we can't re-clone after - # resizing the vdi disk - machine.provider.driver.close_medium(defined_disk["UUID"]) - - # clone back to original vmdk format and attach resized disk - vmdk_disk_file = machine.provider.driver.vdi_to_vmdk(vdi_disk_file) - machine.provider.driver.attach_disk(disk_info[:port], disk_info[:device], vmdk_disk_file, "hdd") - rescue ScriptError, SignalException, StandardError - LOGGER.warn("Vagrant encountered an error while trying to resize a disk. Vagrant will now attempt to reattach and preserve the original disk...") - machine.ui.error(I18n.t("vagrant.cap.configure_disks.recovery_from_resize", - location: original_disk["Location"], - name: machine.name)) - recover_from_resize(machine, disk_info, backup_disk_location, original_disk, vdi_disk_file) - - raise - ensure - # Remove backup disk file if all goes well - FileUtils.remove(backup_disk_location, force: true) - end - - # Remove cloned resized volume format - machine.provider.driver.close_medium(vdi_disk_file) - - # Get new updated disk UUID for vagrant disk_meta file - new_disk_info = machine.provider.driver.list_hdds.select { |h| h["Location"] == defined_disk["Location"] }.first - defined_disk = new_disk_info - else - machine.provider.driver.resize_disk(defined_disk["Location"], disk_config.size.to_i) - end + # TODO: Resize the disks + machine.provider.driver.resize_disk(defined_disk["Location"], disk_config.size.to_i) + # Store updated metadata disk_metadata = {uuid: defined_disk["UUID"], name: disk_config.name} disk_metadata end - - # Recovery method for when an exception occurs during the process of resizing disks - # - # It attempts to move back the backup disk into place, and reattach it to the guest before - # raising the original error - # - # @param [Vagrant::Machine] machine - # @param [Hash] disk_info - The disk device and port number to attach back to - # @param [String] backup_disk_location - The place on disk where vagrant made a backup of the original disk being resized - # @param [Hash] original_disk - The disk information from VirtualBox - # @param [String] vdi_disk_file - The place on disk where vagrant made a clone of the original disk being resized - def self.recover_from_resize(machine, disk_info, backup_disk_location, original_disk, vdi_disk_file) - begin - # move backup to original name - FileUtils.mv(backup_disk_location, original_disk["Location"], force: true) - # Attach disk - machine.provider.driver. - attach_disk(disk_info[:port], disk_info[:device], original_disk["Location"], "hdd") - - # Remove cloned disk if still hanging around - if vdi_disk_file - machine.provider.driver.close_medium(vdi_disk_file) - end - - # We recovered! - machine.ui.warn(I18n.t("vagrant.cap.configure_disks.recovery_attached_disks")) - rescue => e - LOGGER.error("Vagrant encountered an error while trying to recover. It will now show the original error and continue...") - LOGGER.error(e) - end - end end end end From 7be0a6807a6e000842e6f274fd322820a95dbd7f Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 30 Mar 2020 15:20:29 -0700 Subject: [PATCH 09/97] Fix mixed tabs on get_vm_status script --- plugins/providers/hyperv/scripts/get_vm_status.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/scripts/get_vm_status.ps1 b/plugins/providers/hyperv/scripts/get_vm_status.ps1 index dbe538440..5c7630d64 100644 --- a/plugins/providers/hyperv/scripts/get_vm_status.ps1 +++ b/plugins/providers/hyperv/scripts/get_vm_status.ps1 @@ -14,7 +14,7 @@ try # type was loaded in Microsoft.HyperV.PowerShell [void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.HyperV.PowerShell.Objects, Culture=neutral, PublicKeyToken=31bf3856ad364e35') } catch { - # Empty catch ok, since if we didn't load the types, we will fail in the next block + # Empty catch ok, since if we didn't load the types, we will fail in the next block } $VmmsPath = if ([environment]::Is64BitProcess) { "$($env:SystemRoot)\System32\vmms.exe" } else { "$($env:SystemRoot)\Sysnative\vmms.exe" } From 09bd28048ebcd66423df01fef9fca582814be219 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 11:28:51 -0700 Subject: [PATCH 10/97] Add driver method for attaching a new disk for hyper-v guests --- plugins/providers/hyperv/driver.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 4f95db8c7..92222fee2 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -28,6 +28,28 @@ module VagrantPlugins @vm_id = id end + # + # Disk Driver methods + # + + # @param [String] controller_type + # @param [String] controller_number + # @param [String] controller_location + # @param [Hash] opts + def attach_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) + execute(:attach_disk_drive, @vm_id, controller_type, controller_numer, + controller_location, disk_file_path) + end + + def new_vdh(path, size_bytes, **opts) + execute(:new_vdh, @vm_id, path, size_bytes) + end + + + ######## + ######## + ######## + # @return [Boolean] Supports VMCX def has_vmcx_support? !!execute(:has_vmcx_support)["result"] From 26e5cf1d02a7b4cd292c6e852af68d4d05463bdb Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 11:29:05 -0700 Subject: [PATCH 11/97] Add powershell script for attaching a harddisk to a guest --- .../hyperv/scripts/attach_disk_drive.ps1 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 plugins/providers/hyperv/scripts/attach_disk_drive.ps1 diff --git a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 new file mode 100644 index 000000000..5f23e932e --- /dev/null +++ b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 @@ -0,0 +1,19 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$VmId, + [string]$ControllerType, + [string]$ControllerNumber, + [string]$ControllerLocation, + [Parameter(Mandatory=$true)] + [string]$DiskFilePath +) + +try { + $vm = Hyper-V\Get-VM -Id $VmId + Hyper-V\Add-VMHardDiskDrive -VMName $vm -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation -Path $DiskFilePath +} catch { + Write-ErrorMessage "Failed to attach disk ${DiskFilePath} to VM ${vm}: ${PSItem}" + exit 1 +} From 60f2c14b82816601c444db90a1a2fd67c53a4019 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 12:02:07 -0700 Subject: [PATCH 12/97] Update attach disk script --- plugins/providers/hyperv/scripts/attach_disk_drive.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 index 5f23e932e..6856be7a2 100644 --- a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 @@ -11,9 +11,11 @@ param( ) try { - $vm = Hyper-V\Get-VM -Id $VmId - Hyper-V\Add-VMHardDiskDrive -VMName $vm -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation -Path $DiskFilePath + $VM = Hyper-V\Get-VM -Id $VmId + #Hyper-V\Add-VMHardDiskDrive -VMName $vm -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation -Path $DiskFilePath + # Add logic to support missing params. Below is the simple case for attaching a disk + Hyper-V\Add-VMHardDiskDrive -VMName $VM -Path $DiskFilePath } catch { - Write-ErrorMessage "Failed to attach disk ${DiskFilePath} to VM ${vm}: ${PSItem}" + Write-ErrorMessage "Failed to attach disk ${DiskFilePath} to VM ${VM}: ${PSItem}" exit 1 } From 2b8376cda8ee246e7ebc27747a64b37bd52827f9 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 12:02:29 -0700 Subject: [PATCH 13/97] Add additional driver methods for managing disks in hyper-v --- plugins/providers/hyperv/driver.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 92222fee2..064ae835d 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -37,14 +37,27 @@ module VagrantPlugins # @param [String] controller_location # @param [Hash] opts def attach_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) - execute(:attach_disk_drive, @vm_id, controller_type, controller_numer, + execute(:attach_disk_drive, @vm_id, controller_type, controller_number, controller_location, disk_file_path) end + # TODO: Include other options like if disk is fixed or dymanic in opts hash? + # + # @param [String] path + # @param [Int] size_bytes + # @param [Hash] opts def new_vdh(path, size_bytes, **opts) - execute(:new_vdh, @vm_id, path, size_bytes) + # ensure size_bytes is a uint64 + execute(:new_vdh, path, size_bytes) end + # @param [String] controller_type + # @param [String] controller_number + # @param [String] controller_location + # @param [Hash] opts + def remove_disk(controller_type, controller_number, controller_location, **opts) + execute(:remove_disk_drive, @vm_id, controller_type, controller_number, controller_location) + end ######## ######## From 06799f0ff1455f51747150a66b7bdfb5761aa8ad Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 12:02:43 -0700 Subject: [PATCH 14/97] Add driver scripts for disk management --- plugins/providers/hyperv/scripts/new_vdh.ps1 | 15 +++++++++++++ .../hyperv/scripts/remove_disk_drive.ps1 | 21 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 plugins/providers/hyperv/scripts/new_vdh.ps1 create mode 100644 plugins/providers/hyperv/scripts/remove_disk_drive.ps1 diff --git a/plugins/providers/hyperv/scripts/new_vdh.ps1 b/plugins/providers/hyperv/scripts/new_vdh.ps1 new file mode 100644 index 000000000..35ea1bb2b --- /dev/null +++ b/plugins/providers/hyperv/scripts/new_vdh.ps1 @@ -0,0 +1,15 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$DiskFilePath + [Parameter(Mandatory=$true)] + [UInt64]$DiskSizeBytes +) + +try { + Hyper-V\New-VHD -Path $DiskFilePath -SizeBytes $DiskSizeBytes +} catch { + Write-ErrorMessage "Failed to create disk ${DiskFilePath}: ${PSItem}" + exit 1 +} diff --git a/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 b/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 new file mode 100644 index 000000000..ec330dd4d --- /dev/null +++ b/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 @@ -0,0 +1,21 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$VmId, + [Parameter(Mandatory=$true)] + [string]$ControllerType, + [Parameter(Mandatory=$true)] + [string]$ControllerNumber, + [Parameter(Mandatory=$true)] + [string]$ControllerLocation, +) + +try { + $VM = Hyper-V\Get-VM -Id $VmId + + Hyper-v\Remove-VMHardDiskDrive -VMName $VM -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation +} catch { + Write-ErrorMessage "Failed to remove disk ${DiskFilePath} to VM ${VM}: ${PSItem}" + exit 1 +} From d451151ff8faf8a138d7560086dd53e9ac5d14c8 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 13:30:45 -0700 Subject: [PATCH 15/97] Add resize disk driver method --- plugins/providers/hyperv/driver.rb | 7 +++++++ .../hyperv/scripts/resize_disk_drive.ps1 | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 plugins/providers/hyperv/scripts/resize_disk_drive.ps1 diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 064ae835d..26c6b1812 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -59,6 +59,13 @@ module VagrantPlugins execute(:remove_disk_drive, @vm_id, controller_type, controller_number, controller_location) end + # @param [String] path + # @param [Int] size_bytes + # @param [Hash] opts + def resize_disk(disk_file_path, size_bytes, **opts) + execute(:resize_disk_drive, @vm_id, disk_file_path, size_bytes) + end + ######## ######## ######## diff --git a/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 b/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 new file mode 100644 index 000000000..d648f6dd2 --- /dev/null +++ b/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 @@ -0,0 +1,18 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$VmId, + [Parameter(Mandatory=$true)] + [string]$DiskFilePath + [Parameter(Mandatory=$true)] + [string]$DiskSize +) + +try { + $VM = Hyper-V\Get-VM -Id $VmId + Hyper-V\Resize-VHD -Path $DiskFilePath -SizeBytes $DiskSize +} catch { + Write-ErrorMessage "Failed to resize disk ${DiskFilePath} for VM ${VM}: ${PSItem}" + exit 1 +} From 83922333d5e2b3f5dd760336d1c45a9aa2085e77 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 15:09:25 -0700 Subject: [PATCH 16/97] Use UInt64 type instead of String for DiskSize --- plugins/providers/hyperv/scripts/resize_disk_drive.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 b/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 index d648f6dd2..b0907bde6 100644 --- a/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 @@ -6,7 +6,7 @@ param( [Parameter(Mandatory=$true)] [string]$DiskFilePath [Parameter(Mandatory=$true)] - [string]$DiskSize + [UInt64]$DiskSize ) try { From c832394a95cc58fc774f8f1a4e1621f5f6d62bfc Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 31 Mar 2020 15:57:44 -0700 Subject: [PATCH 17/97] Add location of hyper-v disk path --- plugins/providers/hyperv/driver.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 26c6b1812..bcb1c4dbb 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -43,6 +43,11 @@ module VagrantPlugins # TODO: Include other options like if disk is fixed or dymanic in opts hash? # + # Example path for default disk location. Should be able to get this + # for new disks and store them in the same folder + # + # C:\Users\vagrant\test\.vagrant\machines\hashicorp\hyperv\Virtual Hard Disks\ubuntu-18.04-amd64.vhdx + # # @param [String] path # @param [Int] size_bytes # @param [Hash] opts From 50adf04b5da5d094bad140bcb57879ece1fe08f0 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 1 Apr 2020 14:09:29 -0700 Subject: [PATCH 18/97] Add list harddisk method for hyper-v provider --- plugins/providers/hyperv/driver.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index bcb1c4dbb..605080021 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -71,6 +71,10 @@ module VagrantPlugins execute(:resize_disk_drive, @vm_id, disk_file_path, size_bytes) end + def list_hdds + execute(:list_hdds, @vm_id) + end + ######## ######## ######## From 59bbf9736a472945ee2c542e6f2b8f0c3168165a Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 1 Apr 2020 14:09:49 -0700 Subject: [PATCH 19/97] Add powershell script for retreiving disk info for a hyper-v guest --- plugins/providers/hyperv/scripts/list_hdds.ps1 | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 plugins/providers/hyperv/scripts/list_hdds.ps1 diff --git a/plugins/providers/hyperv/scripts/list_hdds.ps1 b/plugins/providers/hyperv/scripts/list_hdds.ps1 new file mode 100644 index 000000000..b4763d5c2 --- /dev/null +++ b/plugins/providers/hyperv/scripts/list_hdds.ps1 @@ -0,0 +1,14 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$VmId +) + +try { + $VM = Hyper-V\Get-VM -Id $VmId + Hyper-V\Get-VMHardDiskDrive -VMName $VM +} catch { + Write-ErrorMessage "Failed to retrieve all disk info from ${VM}: ${PSItem}" + exit 1 +} From a20418ad43074a93bc21b97611c4967713ebc897 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 1 Apr 2020 15:44:54 -0700 Subject: [PATCH 20/97] Format output from json to return to hyper-v driver --- plugins/providers/hyperv/scripts/list_hdds.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/scripts/list_hdds.ps1 b/plugins/providers/hyperv/scripts/list_hdds.ps1 index b4763d5c2..869b7810e 100644 --- a/plugins/providers/hyperv/scripts/list_hdds.ps1 +++ b/plugins/providers/hyperv/scripts/list_hdds.ps1 @@ -7,8 +7,11 @@ param( try { $VM = Hyper-V\Get-VM -Id $VmId - Hyper-V\Get-VMHardDiskDrive -VMName $VM + $Disks = @(Hyper-V\Get-VMHardDiskDrive -VMName $VM) } catch { Write-ErrorMessage "Failed to retrieve all disk info from ${VM}: ${PSItem}" exit 1 } + +$result = ConvertTo-json $Disks +Write-OutputMessage $result From a7a779586a20dca77fc11047bac9e31ac2a5c1f2 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Fri, 3 Apr 2020 16:21:46 -0700 Subject: [PATCH 21/97] Don't limit disk number for hyper-v for now --- plugins/providers/hyperv/cap/configure_disks.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index c489d68e1..f83008396 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -9,10 +9,6 @@ module VagrantPlugins module ConfigureDisks LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::configure_disks") - # The max amount of disks that can be attached to a single device in a controller - # TODO: Figure out if there's a limit for Hyper-V guests - MAX_DISK_NUMBER = 30.freeze - # @param [Vagrant::Machine] machine # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks # @return [Hash] configured_disks - A hash of all the current configured disks @@ -21,11 +17,6 @@ module VagrantPlugins return {} if !Vagrant::Util::Experimental.feature_enabled?("disks") - if defined_disks.size > MAX_DISK_NUMBER - # you can only attach up to 30 disks per controller, INCLUDING the primary disk - raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit - end - machine.ui.info(I18n.t("vagrant.cap.configure_disks.start")) current_disks = machine.provider.driver.list_hdds From fe7705e69474f688bea238ad0eeecf25851bc388 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 7 Apr 2020 09:47:26 -0700 Subject: [PATCH 22/97] Update how disk_ext default is set Prior to this commit, the default value of disk_ext was set in the finalize! method, and was really only valid for the virtualbox provider. This commit updates that by moving the step into the validate function, which has access to the machines provider. --- plugins/kernel_v2/config/disk.rb | 15 ++++++++++++--- test/unit/plugins/kernel_v2/config/disk_test.rb | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index 5c3daf44f..2dc6a2909 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -107,8 +107,6 @@ module VagrantPlugins @size = nil if @size == UNSET_VALUE @file = nil if @file == UNSET_VALUE - @disk_ext = "vdi" if @disk_ext == UNSET_VALUE - if @primary == UNSET_VALUE @primary = false end @@ -135,7 +133,18 @@ module VagrantPlugins types: DEFAULT_DISK_TYPES.join(', ')) end - if @disk_ext + if @disk_ext == UNSET_VALUE + # Work around to finalize disk_ext with a valid default per-provider + if machine.provider_name == :virtualbox + @disk_ext = "vdi" + elsif machine.provider_name == :vmware_desktop + @disk_ext = nil + elsif machine.provider_name == :hyperv + @disk_ext = "vhdx" + else + @disk_ext = "vdi" + end + elsif @disk_ext @disk_ext = @disk_ext.downcase if machine.provider.capability?(:validate_disk_ext) diff --git a/test/unit/plugins/kernel_v2/config/disk_test.rb b/test/unit/plugins/kernel_v2/config/disk_test.rb index 6b6879f37..ebb0f4103 100644 --- a/test/unit/plugins/kernel_v2/config/disk_test.rb +++ b/test/unit/plugins/kernel_v2/config/disk_test.rb @@ -10,7 +10,7 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigDisk do subject { described_class.new(type) } let(:provider) { double("provider") } - let(:machine) { double("machine", provider: provider) } + let(:machine) { double("machine", provider: provider, provider_name: :virtualbox) } def assert_invalid From e8b900936a93a2bd736f5e9cbe0107dc38734ec5 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 7 Apr 2020 15:26:40 -0700 Subject: [PATCH 23/97] Add disk management methods to hyper-v driver actions --- plugins/providers/hyperv/action.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/providers/hyperv/action.rb b/plugins/providers/hyperv/action.rb index c7e1fb939..8925b2ab0 100644 --- a/plugins/providers/hyperv/action.rb +++ b/plugins/providers/hyperv/action.rb @@ -149,6 +149,8 @@ module VagrantPlugins b3.use NetSetMac end + b3.use CleanupDisks + b3.use Disk b3.use StartInstance b3.use WaitForIPAddress b3.use WaitForCommunicator, [:running] From 0675393e0637b5ea178ed31f98731151c5646eee Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 7 Apr 2020 15:28:07 -0700 Subject: [PATCH 24/97] Add named parameters to powershell execute methods in hyper-v driver Parameters to the execute method need to be named to match up to their names inside the parameter arguments for the respective powershell scripts --- plugins/providers/hyperv/driver.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 605080021..53e9fafe2 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -37,8 +37,9 @@ module VagrantPlugins # @param [String] controller_location # @param [Hash] opts def attach_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) - execute(:attach_disk_drive, @vm_id, controller_type, controller_number, - controller_location, disk_file_path) + execute(:attach_disk_drive, VmId: @vm_id, ControllerType: controller_type, + ControllerNumber: controller_number, ControllerLocation: controller_location, + DiskFilePath: disk_file_path) end # TODO: Include other options like if disk is fixed or dymanic in opts hash? @@ -53,7 +54,7 @@ module VagrantPlugins # @param [Hash] opts def new_vdh(path, size_bytes, **opts) # ensure size_bytes is a uint64 - execute(:new_vdh, path, size_bytes) + execute(:new_vdh, DiskFilePath: path, DiskSizeBytes: size_bytes) end # @param [String] controller_type @@ -61,18 +62,20 @@ module VagrantPlugins # @param [String] controller_location # @param [Hash] opts def remove_disk(controller_type, controller_number, controller_location, **opts) - execute(:remove_disk_drive, @vm_id, controller_type, controller_number, controller_location) + execute(:remove_disk_drive, VmId: @vm_id, ControllerType: controller_type, + ControllerNumer: controller_number, ControllerLocation: controller_location) end # @param [String] path # @param [Int] size_bytes # @param [Hash] opts def resize_disk(disk_file_path, size_bytes, **opts) - execute(:resize_disk_drive, @vm_id, disk_file_path, size_bytes) + execute(:resize_disk_drive, VmId: @vm_id, DiskFilePath: disk_file_path, + DiskSize: size_bytes) end def list_hdds - execute(:list_hdds, @vm_id) + execute(:list_hdds, VmId: @vm_id) end ######## From 68354295381384bae16d42764955922bafa2d063 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 7 Apr 2020 15:35:01 -0700 Subject: [PATCH 25/97] Grab correct name to pass along to disk command --- plugins/providers/hyperv/scripts/list_hdds.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/scripts/list_hdds.ps1 b/plugins/providers/hyperv/scripts/list_hdds.ps1 index 869b7810e..b4fab2b76 100644 --- a/plugins/providers/hyperv/scripts/list_hdds.ps1 +++ b/plugins/providers/hyperv/scripts/list_hdds.ps1 @@ -7,7 +7,7 @@ param( try { $VM = Hyper-V\Get-VM -Id $VmId - $Disks = @(Hyper-V\Get-VMHardDiskDrive -VMName $VM) + $Disks = @(Hyper-V\Get-VMHardDiskDrive -VMName $VM.name) } catch { Write-ErrorMessage "Failed to retrieve all disk info from ${VM}: ${PSItem}" exit 1 From c9b2e609a05d28976680c48d4cdde91b73303508 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 8 Apr 2020 17:33:18 -0700 Subject: [PATCH 26/97] Properly grab primary disk from hyper-v vm --- plugins/providers/hyperv/cap/configure_disks.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index f83008396..cfdd2e8f4 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -41,6 +41,10 @@ module VagrantPlugins protected + # TODO: Looks like it's assumed that controllerlocation=0 will be the primary + # disk, so we can use that to configure it. Otherwise, we can match up the disk + # name to the disk config name, like we do with virtualbox + # # @param [Vagrant::Machine] machine - the current machine # @param [Config::Disk] disk - the current disk to configure # @param [Array] all_disks - A list of all currently defined disks in VirtualBox @@ -51,11 +55,11 @@ module VagrantPlugins # Ensure we grab the proper primary disk # We can't rely on the order of `all_disks`, as they will not # always come in port order, but primary is always Port 0 Device 0. - vm_info = machine.provider.driver.show_vm_info - primary_uuid = vm_info["SATA Controller-ImageUUID-0-0"] - current_disk = all_disks.select { |d| d["UUID"] == primary_uuid }.first + current_disk = all_disks.select { |d| d["ControllerLocation"] == 0 && d["ControllerNumber"] == 0 }.first else + # might have to look at the path of the disk, as the disk name doesn't + # make any sense current_disk = all_disks.select { |d| d["Disk Name"] == disk.name}.first end From fb39bd7ed0ffec171ab8c0f14401062cb950af34 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 8 Apr 2020 17:37:36 -0700 Subject: [PATCH 27/97] Use uppercase Name for getting vm name --- plugins/providers/hyperv/scripts/list_hdds.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/scripts/list_hdds.ps1 b/plugins/providers/hyperv/scripts/list_hdds.ps1 index b4fab2b76..907484a33 100644 --- a/plugins/providers/hyperv/scripts/list_hdds.ps1 +++ b/plugins/providers/hyperv/scripts/list_hdds.ps1 @@ -7,7 +7,7 @@ param( try { $VM = Hyper-V\Get-VM -Id $VmId - $Disks = @(Hyper-V\Get-VMHardDiskDrive -VMName $VM.name) + $Disks = @(Hyper-V\Get-VMHardDiskDrive -VMName $VM.Name) } catch { Write-ErrorMessage "Failed to retrieve all disk info from ${VM}: ${PSItem}" exit 1 From 93489ba190004fc998e829acbe85928274aca6fc Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 9 Apr 2020 14:38:52 -0700 Subject: [PATCH 28/97] Add hyper-v driver method for obtaining full disk info given a path --- plugins/providers/hyperv/cap/configure_disks.rb | 3 +++ plugins/providers/hyperv/driver.rb | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index cfdd2e8f4..49397f58a 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -111,6 +111,9 @@ module VagrantPlugins # @return [Boolean] def self.compare_disk_size(machine, disk_config, defined_disk) requested_disk_size = Vagrant::Util::Numeric.bytes_to_megabytes(disk_config.size) + + disk_actual = machine.provider.driver.get_disk(defined_disk["Path"]) + defined_disk_size = defined_disk["Capacity"].split(" ").first.to_f if defined_disk_size > requested_disk_size diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 53e9fafe2..498f5cc67 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -78,6 +78,10 @@ module VagrantPlugins execute(:list_hdds, VmId: @vm_id) end + def get_disk(disk_file_path) + execute(:get_vhd, DiskFilePath: disk_file_path) + end + ######## ######## ######## From 66a22b190a866554d6c101881b2b240c4d4bf841 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 9 Apr 2020 14:39:15 -0700 Subject: [PATCH 29/97] Add powershell script for Get-VHD --- plugins/providers/hyperv/scripts/get_vhd.ps1 | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 plugins/providers/hyperv/scripts/get_vhd.ps1 diff --git a/plugins/providers/hyperv/scripts/get_vhd.ps1 b/plugins/providers/hyperv/scripts/get_vhd.ps1 new file mode 100644 index 000000000..49124167e --- /dev/null +++ b/plugins/providers/hyperv/scripts/get_vhd.ps1 @@ -0,0 +1,16 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$DiskFilePath +) + +try { + $Disk = Hyper-V\Get-VHD -path $DiskFilePath +} catch { + Write-ErrorMessage "Failed to retrieve disk info from disk file path ${DiskFilePath}: ${PSItem}" + exit 1 +} + +$result = ConvertTo-json $Disk +Write-OutputMessage $result From 6cc5de46def4565e7a5af3348ebc539dc6fe4f15 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 9 Apr 2020 15:08:21 -0700 Subject: [PATCH 30/97] Fixup how hyper-v configure disks checks disk size against config --- plugins/providers/hyperv/cap/configure_disks.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 49397f58a..b58fb01af 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -110,13 +110,13 @@ module VagrantPlugins # @param [Hash] defined_disk # @return [Boolean] def self.compare_disk_size(machine, disk_config, defined_disk) - requested_disk_size = Vagrant::Util::Numeric.bytes_to_megabytes(disk_config.size) - + # Hyper-V returns disk size in bytes + requested_disk_size = disk_config.size disk_actual = machine.provider.driver.get_disk(defined_disk["Path"]) - - defined_disk_size = defined_disk["Capacity"].split(" ").first.to_f + defined_disk_size = disk_config.size if defined_disk_size > requested_disk_size + # TODO: Check if disk (maybe use file path) is of type `VHDX`. If not, the disk cannot be shrunk machine.ui.warn(I18n.t("vagrant.cap.configure_disks.shrink_size_not_supported", name: disk_config.name)) return false elsif defined_disk_size < requested_disk_size From 8b28edf5731bfdc6d80aa502981f9abad849c924 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 9 Apr 2020 17:30:32 -0700 Subject: [PATCH 31/97] Comment out disk reattach for now --- .../providers/hyperv/cap/configure_disks.rb | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index b58fb01af..980ff588d 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -85,18 +85,21 @@ module VagrantPlugins elsif compare_disk_size(machine, disk, current_disk) disk_metadata = resize_disk(machine, disk, current_disk) else - # TODO: What if it needs to be resized? + # TODO OLD: What if it needs to be resized? + # + # TODO: Is it possible for a disk to not be connected by this point + # for hyper-v? Since we get the disk from the vm info itself - disk_info = machine.provider.driver.get_port_and_device(current_disk["UUID"]) - if disk_info.empty? - LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest") - dsk_info = get_next_port(machine) - machine.provider.driver.attach_disk(dsk_info[:port], - dsk_info[:device], - current_disk["Location"]) - else - LOGGER.info("No further configuration required for disk '#{disk.name}'") - end + #disk_info = machine.provider.driver.get_port_and_device(current_disk["UUID"]) + #if disk_info.empty? + # LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest") + # dsk_info = get_next_port(machine) + # machine.provider.driver.attach_disk(dsk_info[:port], + # dsk_info[:device], + # current_disk["Location"]) + #else + # LOGGER.info("No further configuration required for disk '#{disk.name}'") + #end disk_metadata = {uuid: current_disk["UUID"], name: disk.name} end From b6c99510c4f3f50412e1518bbda4f30388ef66e5 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 9 Apr 2020 17:30:42 -0700 Subject: [PATCH 32/97] Add notes for creating disks for hyper-v --- plugins/providers/hyperv/cap/configure_disks.rb | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 980ff588d..cf4ca32f1 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -135,15 +135,20 @@ module VagrantPlugins # @param [Kernel_V2::VagrantConfigDisk] disk_config def self.create_disk(machine, disk_config) machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name)) - # NOTE: At the moment, there are no provider specific configs for Hyper-V - # but we grab it anyway for future use. disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config - # TODO: Create and store disk before attaching, if required + # TODO: Create and store disk before attaching + # + # create supporting powershell scripts and hyper-v driver methods + # + # pass along disk_provider_config if defined. This should + # contain various options for creating disks + # Get the machines data dir, that will now be the path for the new disk guest_info = machine.provider.driver.show_vm_info guest_folder = File.dirname(guest_info["CfgFile"]) + # Set the extension disk_ext = disk_config.disk_ext disk_file = File.join(guest_folder, disk_config.name) + ".#{disk_ext}" @@ -152,6 +157,8 @@ module VagrantPlugins disk_var = machine.provider.driver.create_disk(disk_file, disk_config.size, disk_ext.upcase) disk_metadata = {uuid: disk_var.split(':').last.strip, name: disk_config.name} + # This might not be required. If no port is specified, we can just + # attach the disk with the command for hyper-v dsk_controller_info = get_next_port(machine) machine.provider.driver.attach_disk(dsk_controller_info[:port], dsk_controller_info[:device], disk_file) From b79d6bdc272acc73fa01c7881eef5dc1ab108d63 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:35:54 -0700 Subject: [PATCH 33/97] Actually compare disk size with requested size --- plugins/providers/hyperv/cap/configure_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index cf4ca32f1..12b312442 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -116,7 +116,7 @@ module VagrantPlugins # Hyper-V returns disk size in bytes requested_disk_size = disk_config.size disk_actual = machine.provider.driver.get_disk(defined_disk["Path"]) - defined_disk_size = disk_config.size + defined_disk_size = disk_actual["Size"] if defined_disk_size > requested_disk_size # TODO: Check if disk (maybe use file path) is of type `VHDX`. If not, the disk cannot be shrunk From bb2195b692da9c1dc7aeac8d421337fa0d35abba Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:36:06 -0700 Subject: [PATCH 34/97] Add ability to create and attach disks to hyper-v guests --- .../providers/hyperv/cap/configure_disks.rb | 34 ++++++++----------- plugins/providers/hyperv/driver.rb | 2 +- .../hyperv/scripts/attach_disk_drive.ps1 | 2 +- plugins/providers/hyperv/scripts/new_vdh.ps1 | 2 +- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 12b312442..0247e6eb2 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -90,7 +90,7 @@ module VagrantPlugins # TODO: Is it possible for a disk to not be connected by this point # for hyper-v? Since we get the disk from the vm info itself - #disk_info = machine.provider.driver.get_port_and_device(current_disk["UUID"]) + #disk_info = machine.provider.driver.get_port_and_device(current_disk["DiskIdentifier"]) #if disk_info.empty? # LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest") # dsk_info = get_next_port(machine) @@ -101,7 +101,7 @@ module VagrantPlugins # LOGGER.info("No further configuration required for disk '#{disk.name}'") #end - disk_metadata = {uuid: current_disk["UUID"], name: disk.name} + disk_metadata = {uuid: current_disk["DiskIdentifier"], name: disk.name, path: current_disk["Path"]} end disk_metadata @@ -135,32 +135,27 @@ module VagrantPlugins # @param [Kernel_V2::VagrantConfigDisk] disk_config def self.create_disk(machine, disk_config) machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name)) + disk_provider_config = {} disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config - # TODO: Create and store disk before attaching - # - # create supporting powershell scripts and hyper-v driver methods - # - # pass along disk_provider_config if defined. This should - # contain various options for creating disks - # Get the machines data dir, that will now be the path for the new disk - guest_info = machine.provider.driver.show_vm_info - guest_folder = File.dirname(guest_info["CfgFile"]) + guest_disk_folder = machine.data_dir.join("Virtual Hard Disks") # Set the extension disk_ext = disk_config.disk_ext - disk_file = File.join(guest_folder, disk_config.name) + ".#{disk_ext}" + disk_file = File.join(guest_disk_folder, disk_config.name) + ".#{disk_ext}" LOGGER.info("Attempting to create a new disk file '#{disk_file}' of size '#{disk_config.size}' bytes") - disk_var = machine.provider.driver.create_disk(disk_file, disk_config.size, disk_ext.upcase) - disk_metadata = {uuid: disk_var.split(':').last.strip, name: disk_config.name} + machine.provider.driver.create_disk(disk_file, disk_config.size, disk_provider_config) + + disk_info = machine.provider.driver.get_disk(disk_file) + disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} # This might not be required. If no port is specified, we can just # attach the disk with the command for hyper-v - dsk_controller_info = get_next_port(machine) - machine.provider.driver.attach_disk(dsk_controller_info[:port], dsk_controller_info[:device], disk_file) + #dsk_controller_info = get_next_port(machine) + machine.provider.driver.attach_disk(nil, nil, nil, disk_file) disk_metadata end @@ -172,11 +167,12 @@ module VagrantPlugins def self.resize_disk(machine, disk_config, defined_disk) machine.ui.detail(I18n.t("vagrant.cap.configure_disks.resize_disk", name: disk_config.name), prefix: true) - # TODO: Resize the disks - machine.provider.driver.resize_disk(defined_disk["Location"], disk_config.size.to_i) + machine.provider.driver.resize_disk(defined_disk["Path"], disk_config.size.to_i) + + disk_info = machine.provider.driver.get_disk(defined_disk["Path"]) # Store updated metadata - disk_metadata = {uuid: defined_disk["UUID"], name: disk_config.name} + disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} disk_metadata end diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 498f5cc67..76c89377f 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -52,7 +52,7 @@ module VagrantPlugins # @param [String] path # @param [Int] size_bytes # @param [Hash] opts - def new_vdh(path, size_bytes, **opts) + def create_disk(path, size_bytes, **opts) # ensure size_bytes is a uint64 execute(:new_vdh, DiskFilePath: path, DiskSizeBytes: size_bytes) end diff --git a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 index 6856be7a2..10213c359 100644 --- a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 @@ -14,7 +14,7 @@ try { $VM = Hyper-V\Get-VM -Id $VmId #Hyper-V\Add-VMHardDiskDrive -VMName $vm -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation -Path $DiskFilePath # Add logic to support missing params. Below is the simple case for attaching a disk - Hyper-V\Add-VMHardDiskDrive -VMName $VM -Path $DiskFilePath + Hyper-V\Add-VMHardDiskDrive -VMName $VM.Name -Path $DiskFilePath } catch { Write-ErrorMessage "Failed to attach disk ${DiskFilePath} to VM ${VM}: ${PSItem}" exit 1 diff --git a/plugins/providers/hyperv/scripts/new_vdh.ps1 b/plugins/providers/hyperv/scripts/new_vdh.ps1 index 35ea1bb2b..465e1e7e5 100644 --- a/plugins/providers/hyperv/scripts/new_vdh.ps1 +++ b/plugins/providers/hyperv/scripts/new_vdh.ps1 @@ -2,7 +2,7 @@ param( [Parameter(Mandatory=$true)] - [string]$DiskFilePath + [string]$DiskFilePath, [Parameter(Mandatory=$true)] [UInt64]$DiskSizeBytes ) From 441b81c7042fcbac6b88d1f588880f68b777bfd3 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:42:39 -0700 Subject: [PATCH 35/97] Add TODO about getting disk info for disk_meta file --- plugins/providers/hyperv/cap/configure_disks.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 0247e6eb2..12680d5fb 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -101,6 +101,9 @@ module VagrantPlugins # LOGGER.info("No further configuration required for disk '#{disk.name}'") #end + # TODO: You might need to re-run the get_Disk method to get the most up + # to date option for DiskIdentifier. It seems like if you use the data + # from `list_hdds` it doesn't include this value disk_metadata = {uuid: current_disk["DiskIdentifier"], name: disk.name, path: current_disk["Path"]} end From a6e025f3f0e5d802a8b5be85cfb384fb5ac0973c Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:52:54 -0700 Subject: [PATCH 36/97] Fix module name for cleanup_disks in HyperV driver --- plugins/providers/hyperv/cap/cleanup_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index bc960b7c7..2e407502b 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -2,7 +2,7 @@ require "log4r" require "vagrant/util/experimental" module VagrantPlugins - module Hyperv + module HyperV module Cap module CleanupDisks LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::cleanup_disks") From f3f229c681c26d2eb906b613bfd96e7e3abe0b2f Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:57:01 -0700 Subject: [PATCH 37/97] Resize hyper-v disks --- plugins/providers/hyperv/cap/configure_disks.rb | 2 +- plugins/providers/hyperv/scripts/resize_disk_drive.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 12680d5fb..566c2c6be 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -60,7 +60,7 @@ module VagrantPlugins else # might have to look at the path of the disk, as the disk name doesn't # make any sense - current_disk = all_disks.select { |d| d["Disk Name"] == disk.name}.first + current_disk = all_disks.select { |d| File.basename(d["Path"], '.*') == disk.name}.first end current_disk diff --git a/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 b/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 index b0907bde6..c890ecd4a 100644 --- a/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/resize_disk_drive.ps1 @@ -4,7 +4,7 @@ param( [Parameter(Mandatory=$true)] [string]$VmId, [Parameter(Mandatory=$true)] - [string]$DiskFilePath + [string]$DiskFilePath, [Parameter(Mandatory=$true)] [UInt64]$DiskSize ) From 6b7b4b2c3bb53ad393d8f1feaee8a6b4a679661d Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:57:51 -0700 Subject: [PATCH 38/97] Add todo for cleanup disk action --- plugins/providers/hyperv/cap/cleanup_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 2e407502b..815d0360a 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -25,7 +25,7 @@ module VagrantPlugins # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks # @param [Hash] disk_meta - A hash of all the previously defined disks from the last configure_disk action def self.handle_cleanup_disk(machine, defined_disks, disk_meta) - # Iterate over each disk_meta disk, check if it's still defined in the + # TODO: Iterate over each disk_meta disk, check if it's still defined in the # guests config, and if it's no longer there, remove it from the guest disk_meta.each do |d| # find d in defined_disk From 8f6b18f992516983b67d407266f47f5460d13d38 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 14:58:45 -0700 Subject: [PATCH 39/97] Add note about obtaining disk name in hyper-v --- plugins/providers/hyperv/cap/configure_disks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 566c2c6be..510ffc72d 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -58,8 +58,8 @@ module VagrantPlugins current_disk = all_disks.select { |d| d["ControllerLocation"] == 0 && d["ControllerNumber"] == 0 }.first else - # might have to look at the path of the disk, as the disk name doesn't - # make any sense + # Hyper-V disk names aren't the actual names of the disk, so we have + # to grab the name from the file path instead current_disk = all_disks.select { |d| File.basename(d["Path"], '.*') == disk.name}.first end From 2108b5a695ca3e437f994eeb3096152b46b0cc24 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 13 Apr 2020 16:08:49 -0700 Subject: [PATCH 40/97] Begin to handle cleaning up disks with hyper-v --- plugins/providers/hyperv/cap/cleanup_disks.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 815d0360a..fc3322d2b 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -31,6 +31,17 @@ module VagrantPlugins # find d in defined_disk # if found, continue on # else, remove the disk + + # look at Path instead of Name or UUID + disk_name = File.basename(d["path"], '.*') + dsk = defined_disks.select { |dk| dk.name == disk_name } + primary_disk_uuid = "" + ## todo: finish this + if !dsk.empty? || d["uuid"] == primary_disk_uuid + next + else + #remove disk from guest, and remove from system + end end end end From ac5cc68e55ccf19640de44c4495839e5212c61d7 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 10:42:58 -0700 Subject: [PATCH 41/97] Obtain primary disk UUID to save for disk_meta file --- plugins/providers/hyperv/cap/configure_disks.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 510ffc72d..ec83ef6db 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -57,6 +57,10 @@ module VagrantPlugins # always come in port order, but primary is always Port 0 Device 0. current_disk = all_disks.select { |d| d["ControllerLocation"] == 0 && d["ControllerNumber"] == 0 }.first + + # Need to get actual disk info to obtain UUID + real_disk_info = machine.provider.driver.get_disk(current_disk["Path"]) + current_disk = real_disk_info else # Hyper-V disk names aren't the actual names of the disk, so we have # to grab the name from the file path instead @@ -101,9 +105,6 @@ module VagrantPlugins # LOGGER.info("No further configuration required for disk '#{disk.name}'") #end - # TODO: You might need to re-run the get_Disk method to get the most up - # to date option for DiskIdentifier. It seems like if you use the data - # from `list_hdds` it doesn't include this value disk_metadata = {uuid: current_disk["DiskIdentifier"], name: disk.name, path: current_disk["Path"]} end From f792b5870441108734261b7e19f03e2d53d9fa4b Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 11:50:30 -0700 Subject: [PATCH 42/97] Add functionality to clean up stale disks for hyper-v guests --- plugins/providers/hyperv/cap/cleanup_disks.rb | 23 +++++++++++-------- .../providers/hyperv/cap/configure_disks.rb | 6 +++++ .../hyperv/scripts/remove_disk_drive.ps1 | 4 ++-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index fc3322d2b..41e4e4546 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -25,22 +25,25 @@ module VagrantPlugins # @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks # @param [Hash] disk_meta - A hash of all the previously defined disks from the last configure_disk action def self.handle_cleanup_disk(machine, defined_disks, disk_meta) - # TODO: Iterate over each disk_meta disk, check if it's still defined in the - # guests config, and if it's no longer there, remove it from the guest - disk_meta.each do |d| - # find d in defined_disk - # if found, continue on - # else, remove the disk + all_disks = machine.provider.driver.list_hdds + disk_meta.each do |d| # look at Path instead of Name or UUID disk_name = File.basename(d["path"], '.*') dsk = defined_disks.select { |dk| dk.name == disk_name } - primary_disk_uuid = "" - ## todo: finish this - if !dsk.empty? || d["uuid"] == primary_disk_uuid + + + if !dsk.empty? || d["primary"] == true next else - #remove disk from guest, and remove from system + LOGGER.warn("Found disk not in Vagrantfile config: '#{d["name"]}'. Removing disk from guest #{machine.name}") + disk_info = machine.provider.driver.get_disk(d["path"]) + + machine.ui.warn("Disk '#{d["name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) + + disk_actual = all_disks.select { |a| a["Path"] == d["path"] }.first + + machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["DiskLocation"]) end end end diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index ec83ef6db..27fb69c26 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -93,6 +93,9 @@ module VagrantPlugins # # TODO: Is it possible for a disk to not be connected by this point # for hyper-v? Since we get the disk from the vm info itself + # + # note: hyper-v has a key `"Attached"` that can be used to see if + # the disk is currently attached to a guest #disk_info = machine.provider.driver.get_port_and_device(current_disk["DiskIdentifier"]) #if disk_info.empty? @@ -106,6 +109,9 @@ module VagrantPlugins #end disk_metadata = {uuid: current_disk["DiskIdentifier"], name: disk.name, path: current_disk["Path"]} + if disk.primary + disk_metadata[:primary] = true + end end disk_metadata diff --git a/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 b/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 index ec330dd4d..0d24d7ed5 100644 --- a/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 @@ -8,13 +8,13 @@ param( [Parameter(Mandatory=$true)] [string]$ControllerNumber, [Parameter(Mandatory=$true)] - [string]$ControllerLocation, + [string]$ControllerLocation ) try { $VM = Hyper-V\Get-VM -Id $VmId - Hyper-v\Remove-VMHardDiskDrive -VMName $VM -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation + Hyper-v\Remove-VMHardDiskDrive -VMName $VM.Name -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation } catch { Write-ErrorMessage "Failed to remove disk ${DiskFilePath} to VM ${VM}: ${PSItem}" exit 1 From b99143866c759a681ee7527397e994d5b45dd52f Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 12:05:51 -0700 Subject: [PATCH 43/97] Fix typo for ControllerNumber param --- plugins/providers/hyperv/cap/cleanup_disks.rb | 5 ++++- plugins/providers/hyperv/driver.rb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 41e4e4546..23ebb775e 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -43,7 +43,10 @@ module VagrantPlugins disk_actual = all_disks.select { |a| a["Path"] == d["path"] }.first - machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["DiskLocation"]) + machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["ControllerLocation"]) + + # TODO: delete disk + # maybe we can just "dismount" instead of removing the disk all together end end end diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 76c89377f..d7fcb6521 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -63,7 +63,7 @@ module VagrantPlugins # @param [Hash] opts def remove_disk(controller_type, controller_number, controller_location, **opts) execute(:remove_disk_drive, VmId: @vm_id, ControllerType: controller_type, - ControllerNumer: controller_number, ControllerLocation: controller_location) + ControllerNumber: controller_number, ControllerLocation: controller_location) end # @param [String] path From b66a61a58d7d8340b27086bbffd9e5f23d72e329 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 13:16:44 -0700 Subject: [PATCH 44/97] Add Dismount-VHD driver method for hyper-v --- plugins/providers/hyperv/driver.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index d7fcb6521..d459905d8 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -82,6 +82,10 @@ module VagrantPlugins execute(:get_vhd, DiskFilePath: disk_file_path) end + def dismount_disk(disk_file_path) + execute(:dismount_vhd, DiskFilePath: disk_file_path) + end + ######## ######## ######## From b3a7bd456678b9b4f3d8c7315c546460abd08f6c Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 13:16:59 -0700 Subject: [PATCH 45/97] Add dismount_vhd powershell script --- plugins/providers/hyperv/scripts/dismount_vhd.ps1 | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 plugins/providers/hyperv/scripts/dismount_vhd.ps1 diff --git a/plugins/providers/hyperv/scripts/dismount_vhd.ps1 b/plugins/providers/hyperv/scripts/dismount_vhd.ps1 new file mode 100644 index 000000000..e53e359bf --- /dev/null +++ b/plugins/providers/hyperv/scripts/dismount_vhd.ps1 @@ -0,0 +1,13 @@ +#Requires -Modules VagrantMessages + +param( + [Parameter(Mandatory=$true)] + [string]$DiskFilePath +) + +try { + Hyper-V\Dismount-VHD -path $DiskFilePath +} catch { + Write-ErrorMessage "Failed to dismount disk info from disk file path ${DiskFilePath}: ${PSItem}" + exit 1 +} From 318eb4e65add2d2583dd3c76e0c944286783e633 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 13:27:24 -0700 Subject: [PATCH 46/97] Update method docs in hyperv driver --- plugins/providers/hyperv/driver.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index d459905d8..6808a7e67 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -44,11 +44,6 @@ module VagrantPlugins # TODO: Include other options like if disk is fixed or dymanic in opts hash? # - # Example path for default disk location. Should be able to get this - # for new disks and store them in the same folder - # - # C:\Users\vagrant\test\.vagrant\machines\hashicorp\hyperv\Virtual Hard Disks\ubuntu-18.04-amd64.vhdx - # # @param [String] path # @param [Int] size_bytes # @param [Hash] opts @@ -78,10 +73,12 @@ module VagrantPlugins execute(:list_hdds, VmId: @vm_id) end + # @param [String] disk_file_path def get_disk(disk_file_path) execute(:get_vhd, DiskFilePath: disk_file_path) end + # @param [String] disk_file_path def dismount_disk(disk_file_path) execute(:dismount_vhd, DiskFilePath: disk_file_path) end From 5405aaac82ab38924cc80f4d19bf86babae5d523 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 14:01:39 -0700 Subject: [PATCH 47/97] Remove disk file after detaching from hyper-v guest --- plugins/providers/hyperv/cap/cleanup_disks.rb | 5 +---- plugins/providers/hyperv/driver.rb | 5 +++-- plugins/providers/hyperv/scripts/remove_disk_drive.ps1 | 6 +++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 23ebb775e..3a9efd7ac 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -43,10 +43,7 @@ module VagrantPlugins disk_actual = all_disks.select { |a| a["Path"] == d["path"] }.first - machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["ControllerLocation"]) - - # TODO: delete disk - # maybe we can just "dismount" instead of removing the disk all together + machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["ControllerLocation"], disk_actual["Path"]) end end end diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 6808a7e67..fb9044517 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -56,9 +56,10 @@ module VagrantPlugins # @param [String] controller_number # @param [String] controller_location # @param [Hash] opts - def remove_disk(controller_type, controller_number, controller_location, **opts) + def remove_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) execute(:remove_disk_drive, VmId: @vm_id, ControllerType: controller_type, - ControllerNumber: controller_number, ControllerLocation: controller_location) + ControllerNumber: controller_number, ControllerLocation: controller_location, + DiskFilePath: disk_file_path) end # @param [String] path diff --git a/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 b/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 index 0d24d7ed5..caff08e68 100644 --- a/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/remove_disk_drive.ps1 @@ -8,13 +8,17 @@ param( [Parameter(Mandatory=$true)] [string]$ControllerNumber, [Parameter(Mandatory=$true)] - [string]$ControllerLocation + [string]$ControllerLocation, + [Parameter(Mandatory=$true)] + [string]$DiskFilePath ) try { $VM = Hyper-V\Get-VM -Id $VmId Hyper-v\Remove-VMHardDiskDrive -VMName $VM.Name -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation + + Remove-Item -Path $DiskFilePath } catch { Write-ErrorMessage "Failed to remove disk ${DiskFilePath} to VM ${VM}: ${PSItem}" exit 1 From a3c2e31f01a3dbda2a14b3804ec20742822871b5 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 14:09:38 -0700 Subject: [PATCH 48/97] Set default disk format for vmware_desktop --- plugins/kernel_v2/config/disk.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index 2dc6a2909..c1e9595af 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -138,7 +138,7 @@ module VagrantPlugins if machine.provider_name == :virtualbox @disk_ext = "vdi" elsif machine.provider_name == :vmware_desktop - @disk_ext = nil + @disk_ext = "vmdk" elsif machine.provider_name == :hyperv @disk_ext = "vhdx" else From 20c4325d0aaff92fb58d55d13b55b536b4932c02 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 14:32:32 -0700 Subject: [PATCH 49/97] Update code docs for hyperv disk management --- plugins/providers/hyperv/cap/cleanup_disks.rb | 1 - plugins/providers/hyperv/cap/configure_disks.rb | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index 3a9efd7ac..cf78e821f 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -32,7 +32,6 @@ module VagrantPlugins disk_name = File.basename(d["path"], '.*') dsk = defined_disks.select { |dk| dk.name == disk_name } - if !dsk.empty? || d["primary"] == true next else diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 27fb69c26..d6de9d46e 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -41,10 +41,6 @@ module VagrantPlugins protected - # TODO: Looks like it's assumed that controllerlocation=0 will be the primary - # disk, so we can use that to configure it. Otherwise, we can match up the disk - # name to the disk config name, like we do with virtualbox - # # @param [Vagrant::Machine] machine - the current machine # @param [Config::Disk] disk - the current disk to configure # @param [Array] all_disks - A list of all currently defined disks in VirtualBox @@ -54,11 +50,15 @@ module VagrantPlugins if disk.primary # Ensure we grab the proper primary disk # We can't rely on the order of `all_disks`, as they will not - # always come in port order, but primary is always Port 0 Device 0. + # always come in port order, but primary should always be Location 0 Number 0. current_disk = all_disks.select { |d| d["ControllerLocation"] == 0 && d["ControllerNumber"] == 0 }.first - # Need to get actual disk info to obtain UUID + # Need to get actual disk info to obtain UUID instead of what's returned + # + # This is not required for newly created disks, as its metadata is + # set when creating and attaching the disk. This is only for the primary + # disk, since it already exists. real_disk_info = machine.provider.driver.get_disk(current_disk["Path"]) current_disk = real_disk_info else From 82a6c2c8c1a13a8056920f861eda8752ff16173c Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 14:32:51 -0700 Subject: [PATCH 50/97] Add TODO for attaching disks on start up if left in bad state --- .../providers/hyperv/cap/configure_disks.rb | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index d6de9d46e..36d124574 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -90,20 +90,14 @@ module VagrantPlugins disk_metadata = resize_disk(machine, disk, current_disk) else # TODO OLD: What if it needs to be resized? - # - # TODO: Is it possible for a disk to not be connected by this point - # for hyper-v? Since we get the disk from the vm info itself - # - # note: hyper-v has a key `"Attached"` that can be used to see if - # the disk is currently attached to a guest - #disk_info = machine.provider.driver.get_port_and_device(current_disk["DiskIdentifier"]) - #if disk_info.empty? + # Can't use "attached" attribute, because it is false when the guest + # is powered off + # + #disk_info = machine.provider.driver.get_disk(current_disk["Path"]) + #if disk_info["Attached"] == false # LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest") - # dsk_info = get_next_port(machine) - # machine.provider.driver.attach_disk(dsk_info[:port], - # dsk_info[:device], - # current_disk["Location"]) + # machine.provider.driver.attach_disk(nil, nil, nil, current_disk["Path"]) #else # LOGGER.info("No further configuration required for disk '#{disk.name}'") #end From f2bcf86aca83d25dd76f9ed373dad22a187362a9 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 14:33:05 -0700 Subject: [PATCH 51/97] Allow shrinking vhdx disk formats for hyperv provider --- plugins/providers/hyperv/cap/configure_disks.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 36d124574..0782d1e9d 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -123,9 +123,13 @@ module VagrantPlugins defined_disk_size = disk_actual["Size"] if defined_disk_size > requested_disk_size - # TODO: Check if disk (maybe use file path) is of type `VHDX`. If not, the disk cannot be shrunk - machine.ui.warn(I18n.t("vagrant.cap.configure_disks.shrink_size_not_supported", name: disk_config.name)) - return false + if File.extname(disk_actual["Path"]) == ".vhdx" + # VHDX formats can be shrunk + return true + else + machine.ui.warn(I18n.t("vagrant.cap.configure_disks.shrink_size_not_supported", name: disk_config.name)) + return false + end elsif defined_disk_size < requested_disk_size return true else From ed0fdbf86861d143b7b457ca02eeac1eacd5732e Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 14:39:57 -0700 Subject: [PATCH 52/97] Add note about attaching disks --- plugins/providers/hyperv/cap/configure_disks.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 0782d1e9d..f8a43a87a 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -160,9 +160,7 @@ module VagrantPlugins disk_info = machine.provider.driver.get_disk(disk_file) disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} - # This might not be required. If no port is specified, we can just - # attach the disk with the command for hyper-v - #dsk_controller_info = get_next_port(machine) + # TODO: Should we be passing in controller info? machine.provider.driver.attach_disk(nil, nil, nil, disk_file) disk_metadata From 5258c68cf2ae35baa47f523c553c2b13671e96ab Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 14 Apr 2020 15:00:50 -0700 Subject: [PATCH 53/97] Fixup disk unit tests --- test/unit/plugins/kernel_v2/config/vm_test.rb | 2 +- test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb | 2 -- test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/test/unit/plugins/kernel_v2/config/vm_test.rb b/test/unit/plugins/kernel_v2/config/vm_test.rb index 848cc5ba8..c6e26ff9c 100644 --- a/test/unit/plugins/kernel_v2/config/vm_test.rb +++ b/test/unit/plugins/kernel_v2/config/vm_test.rb @@ -8,7 +8,7 @@ describe VagrantPlugins::Kernel_V2::VMConfig do subject { described_class.new } let(:provider) { double("provider") } - let(:machine) { double("machine", provider: provider) } + let(:machine) { double("machine", provider: provider, provider_name: "provider") } def assert_invalid errors = subject.validate(machine) diff --git a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb index 18ec85d7c..ab1129ccf 100644 --- a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb @@ -1,5 +1,3 @@ -require_relative "../base" - require Vagrant.source_root.join("plugins/providers/hyperv/cap/cleanup_disks") describe VagrantPlugins::HyperV::Cap::CleanupDisks do diff --git a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb index 1c076d897..fb164e3e2 100644 --- a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb @@ -1,5 +1,3 @@ -require_relative "../base" - require Vagrant.source_root.join("plugins/providers/hyperv/cap/configure_disks") describe VagrantPlugins::HyperV::Cap::ConfigureDisks do From 1dbda081d2634f8a15dda7561dfbaa281aa29aab Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 15 Apr 2020 16:32:08 -0700 Subject: [PATCH 54/97] Add notes for creating disk options --- plugins/providers/hyperv/cap/configure_disks.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index f8a43a87a..2826c0baa 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -139,6 +139,13 @@ module VagrantPlugins # Creates and attaches a disk to a machine # + # Extra params: + # - Fixed: true + # - BlockSizeBytes: must be 512 or 4096 + # - LogicalSectorSizeBytes: must be 512 or 4096 + # - PhysicalSectorSizeBytes: must be 512 or 4096 + # - SourceDisk: file path + # # @param [Vagrant::Machine] machine # @param [Kernel_V2::VagrantConfigDisk] disk_config def self.create_disk(machine, disk_config) From cc2dc9a1e1737b43a64dea25118e67a6c1e0acc6 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 15 Apr 2020 16:32:17 -0700 Subject: [PATCH 55/97] Use disk file from config if defined --- plugins/providers/hyperv/cap/configure_disks.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 2826c0baa..9879c6e0b 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -156,13 +156,17 @@ module VagrantPlugins # Get the machines data dir, that will now be the path for the new disk guest_disk_folder = machine.data_dir.join("Virtual Hard Disks") - # Set the extension - disk_ext = disk_config.disk_ext - disk_file = File.join(guest_disk_folder, disk_config.name) + ".#{disk_ext}" + if disk_config.file + disk_file = disk_config.file + else + # Set the extension + disk_ext = disk_config.disk_ext + disk_file = File.join(guest_disk_folder, disk_config.name) + ".#{disk_ext}" - LOGGER.info("Attempting to create a new disk file '#{disk_file}' of size '#{disk_config.size}' bytes") + LOGGER.info("Attempting to create a new disk file '#{disk_file}' of size '#{disk_config.size}' bytes") - machine.provider.driver.create_disk(disk_file, disk_config.size, disk_provider_config) + machine.provider.driver.create_disk(disk_file, disk_config.size, disk_provider_config) + end disk_info = machine.provider.driver.get_disk(disk_file) disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} From 2de5ef0bf21f51a0676c9b98f49b096089de9232 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 16 Apr 2020 14:27:27 -0700 Subject: [PATCH 56/97] Fix typo in new_vhd powershell script name --- plugins/providers/hyperv/driver.rb | 2 +- plugins/providers/hyperv/scripts/{new_vdh.ps1 => new_vhd.ps1} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename plugins/providers/hyperv/scripts/{new_vdh.ps1 => new_vhd.ps1} (100%) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index fb9044517..d68c8385f 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -49,7 +49,7 @@ module VagrantPlugins # @param [Hash] opts def create_disk(path, size_bytes, **opts) # ensure size_bytes is a uint64 - execute(:new_vdh, DiskFilePath: path, DiskSizeBytes: size_bytes) + execute(:new_vhd, DiskFilePath: path, DiskSizeBytes: size_bytes) end # @param [String] controller_type diff --git a/plugins/providers/hyperv/scripts/new_vdh.ps1 b/plugins/providers/hyperv/scripts/new_vhd.ps1 similarity index 100% rename from plugins/providers/hyperv/scripts/new_vdh.ps1 rename to plugins/providers/hyperv/scripts/new_vhd.ps1 From cafb6ec2397b8d3a04370a391c6a375b7fe2c77c Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 20 Apr 2020 15:26:14 -0700 Subject: [PATCH 57/97] Remove extra provider_config option --- plugins/kernel_v2/config/disk.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index c1e9595af..f4499bdf6 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -119,7 +119,12 @@ module VagrantPlugins end end - @provider_config = nil if @provider_config == {} + # TODO: fix me?? + if @provider_config.empty? + @provider_config = nil + else + @provider_config = @provider_config[:provider_config] + end end # @return [Array] array of strings of error messages from config option validation From f798afa0c0a716730f6aca704bcf1005a866688f Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 20 Apr 2020 15:26:25 -0700 Subject: [PATCH 58/97] Attempt to pass along parameters --- plugins/providers/hyperv/driver.rb | 5 +-- plugins/providers/hyperv/scripts/new_vhd.ps1 | 42 ++++++++++++++++++-- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index d68c8385f..fa0f27371 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -42,14 +42,12 @@ module VagrantPlugins DiskFilePath: disk_file_path) end - # TODO: Include other options like if disk is fixed or dymanic in opts hash? - # # @param [String] path # @param [Int] size_bytes # @param [Hash] opts def create_disk(path, size_bytes, **opts) # ensure size_bytes is a uint64 - execute(:new_vhd, DiskFilePath: path, DiskSizeBytes: size_bytes) + execute(:new_vhd, Path: path, SizeBytes: size_bytes, **opts) end # @param [String] controller_type @@ -287,6 +285,7 @@ module VagrantPlugins options = options || {} ps_options = [] options.each do |key, value| + next if value == '' || value.nil? next if value == false ps_options << "-#{key}" # If the value is a TrueClass assume switch diff --git a/plugins/providers/hyperv/scripts/new_vhd.ps1 b/plugins/providers/hyperv/scripts/new_vhd.ps1 index 465e1e7e5..38333e546 100644 --- a/plugins/providers/hyperv/scripts/new_vhd.ps1 +++ b/plugins/providers/hyperv/scripts/new_vhd.ps1 @@ -2,13 +2,49 @@ param( [Parameter(Mandatory=$true)] - [string]$DiskFilePath, + [string]$Path, [Parameter(Mandatory=$true)] - [UInt64]$DiskSizeBytes + [UInt64]$SizeBytes, + [switch]$Fixed, + [UInt32]$BlockSizeBytes, + [UInt32]$LogicalSectorSizeBytes, + [UInt32]$PhysicalSectorSizeBytes ) +$Params = @{ + Path = $Path + SizeBytes = $SizeBytes +} + +if ($Fixed -ne '') { + $Params.Add("Fixed", $true) +} + +if ($BlockSizeBytes -ne '') { + $Params.Add("BlockSizeBytes", $BlockSizeBytes) +} + +if ($LogicalSectorSizeBytes -ne '') { + $Params.Add("LogicalSectorSizeBytes", $LogicalSectorSizeBytes) +} + + +if ($PhysicalSectorSizeBytes -ne '') { + $Params.Add("PhysicalSectorSizeBytes", $PhysicalSectorSizeBytes) +} + +# Maybe try default values for params so don't have to deal with null + +#foreach ($key in $MyInvocation.BoundParameters.keys) { +# $value = (Get-Variable -Exclude "ErrorAction" $key).Value +# +# if ($value -ne $null) { +# $Params.Add($key, $value) +# } +#} + try { - Hyper-V\New-VHD -Path $DiskFilePath -SizeBytes $DiskSizeBytes + Hyper-V\New-VHD @Params } catch { Write-ErrorMessage "Failed to create disk ${DiskFilePath}: ${PSItem}" exit 1 From 9e8343fc931f256c1e62a5bb5c6b5b59003bb39c Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 11:44:09 -0700 Subject: [PATCH 59/97] Automatically add all passed in parameters to hyper-v command --- plugins/providers/hyperv/driver.rb | 4 +- plugins/providers/hyperv/scripts/new_vhd.ps1 | 43 +++++--------------- 2 files changed, 13 insertions(+), 34 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index fa0f27371..3c9a013f9 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -47,7 +47,9 @@ module VagrantPlugins # @param [Hash] opts def create_disk(path, size_bytes, **opts) # ensure size_bytes is a uint64 - execute(:new_vhd, Path: path, SizeBytes: size_bytes, **opts) + execute(:new_vhd, Path: path, SizeBytes: size_bytes, Fixed: opts[:Fixed], + BlockSizeBytes: opts[:BlockSizeBytes], LogicalSectorSizeBytes: opts[:LogicalSectorSizeBytes], + PhysicalSectorSizeBytes: opts[:PhsyicalSectorSizeBytes]) end # @param [String] controller_type diff --git a/plugins/providers/hyperv/scripts/new_vhd.ps1 b/plugins/providers/hyperv/scripts/new_vhd.ps1 index 38333e546..ded00f2f5 100644 --- a/plugins/providers/hyperv/scripts/new_vhd.ps1 +++ b/plugins/providers/hyperv/scripts/new_vhd.ps1 @@ -6,43 +6,20 @@ param( [Parameter(Mandatory=$true)] [UInt64]$SizeBytes, [switch]$Fixed, - [UInt32]$BlockSizeBytes, - [UInt32]$LogicalSectorSizeBytes, - [UInt32]$PhysicalSectorSizeBytes + [string]$BlockSizeBytes, + [string]$LogicalSectorSizeBytes, + [string]$PhysicalSectorSizeBytes ) -$Params = @{ - Path = $Path - SizeBytes = $SizeBytes +$Params = @{} + +foreach ($key in $MyInvocation.BoundParameters.keys) { + $value = (Get-Variable -Exclude "ErrorAction" $key).Value + if ($key -ne "ErrorAction") { + $Params.Add($key, $value) + } } -if ($Fixed -ne '') { - $Params.Add("Fixed", $true) -} - -if ($BlockSizeBytes -ne '') { - $Params.Add("BlockSizeBytes", $BlockSizeBytes) -} - -if ($LogicalSectorSizeBytes -ne '') { - $Params.Add("LogicalSectorSizeBytes", $LogicalSectorSizeBytes) -} - - -if ($PhysicalSectorSizeBytes -ne '') { - $Params.Add("PhysicalSectorSizeBytes", $PhysicalSectorSizeBytes) -} - -# Maybe try default values for params so don't have to deal with null - -#foreach ($key in $MyInvocation.BoundParameters.keys) { -# $value = (Get-Variable -Exclude "ErrorAction" $key).Value -# -# if ($value -ne $null) { -# $Params.Add($key, $value) -# } -#} - try { Hyper-V\New-VHD @Params } catch { From bbe9a637e785184218b26f4b1bff184357263496 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 11:44:32 -0700 Subject: [PATCH 60/97] Convert size options into byte form --- .../providers/hyperv/cap/configure_disks.rb | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 9879c6e0b..0fb1e7e1e 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -153,6 +153,10 @@ module VagrantPlugins disk_provider_config = {} disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config + if !disk_provider_config.empty? + disk_provider_config = convert_size_vars!(disk_provider_config) + end + # Get the machines data dir, that will now be the path for the new disk guest_disk_folder = machine.data_dir.join("Virtual Hard Disks") @@ -172,11 +176,50 @@ module VagrantPlugins disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} # TODO: Should we be passing in controller info? - machine.provider.driver.attach_disk(nil, nil, nil, disk_file) + machine.provider.driver.attach_disk(disk_file, disk_provider_config) disk_metadata end + # Converts any "shortcut" options such as "123MB" into its byte form. This + # is due to what parameter type is expected when calling the `New-VHD` + # powershell command + # + # @param [Hash] disk_provider_config + # @return [Hash] disk_provider_config + def self.convert_size_vars!(disk_provider_config) + conversion_keys = [:BlockSizeBytes, :LogicalSectorSizeBytes, :PhysicalSectorSizeBytes] + + conversion_keys.each do |k| + if disk_provider_config.keys.include?(k) + if k.is_a? Integer + # Assume it is bytes + bytes = disk_provider_config[k] + elsif k == :BlockSizeBytes + bytes = Vagrant::Util::Numeric.string_to_bytes(disk_provider_config[k]) + elsif k == :LogicalSectorSizeBytes || k == :PhysicalSectorSizeBytes + # Logical and Physical can only be these exact values, so converting it + # won't work + case disk_provider_config[k] + when "4096MB" + bytes = 4096 + when "512MB" + bytes = 512 + else + # Their config is wrong + bytes = disk_provider_config[k] + end + else + bytes = disk_provider_config[k] + end + + disk_provider_config[k] = bytes + end + end + + disk_provider_config + end + # @param [Vagrant::Machine] machine # @param [Config::Disk] disk_config - the current disk to configure # @param [Hash] defined_disk - current disk as represented by VirtualBox From d30482a502a970f9a20f97eb27485597f466add6 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 11:44:44 -0700 Subject: [PATCH 61/97] Explicitly pass along optional params --- plugins/providers/hyperv/driver.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 3c9a013f9..edd226fa6 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -36,10 +36,9 @@ module VagrantPlugins # @param [String] controller_number # @param [String] controller_location # @param [Hash] opts - def attach_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) - execute(:attach_disk_drive, VmId: @vm_id, ControllerType: controller_type, - ControllerNumber: controller_number, ControllerLocation: controller_location, - DiskFilePath: disk_file_path) + def attach_disk(disk_file_path, **opts) + execute(:attach_disk_drive, VmId: @vm_id, DiskFilePath: disk_file_path, ControllerType: opts[:ControllerType], + ControllerNumber: opts[:ControllerNumer], ControllerLocation: opts[:ControllerLocation]) end # @param [String] path From 0c19e6da2683b3a5e9a3f9fab75f783efa5b6d85 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 13:40:27 -0700 Subject: [PATCH 62/97] Fix typo --- plugins/providers/hyperv/driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index edd226fa6..79a35b1bd 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -38,7 +38,7 @@ module VagrantPlugins # @param [Hash] opts def attach_disk(disk_file_path, **opts) execute(:attach_disk_drive, VmId: @vm_id, DiskFilePath: disk_file_path, ControllerType: opts[:ControllerType], - ControllerNumber: opts[:ControllerNumer], ControllerLocation: opts[:ControllerLocation]) + ControllerNumber: opts[:ControllerNumber], ControllerLocation: opts[:ControllerLocation]) end # @param [String] path From bb4541a2a5b1b5e3b1bd40cf0b5b4ed7484b826a Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 13:40:33 -0700 Subject: [PATCH 63/97] Remove stale comment --- plugins/providers/hyperv/cap/configure_disks.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 0fb1e7e1e..6aecab08f 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -175,7 +175,6 @@ module VagrantPlugins disk_info = machine.provider.driver.get_disk(disk_file) disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} - # TODO: Should we be passing in controller info? machine.provider.driver.attach_disk(disk_file, disk_provider_config) disk_metadata From 1d8db2734039dc35e0436cbf74238ea6fd297ea7 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 14:07:11 -0700 Subject: [PATCH 64/97] Fixup handling parameters for hyper-v powershell disk scripts --- plugins/providers/hyperv/driver.rb | 6 ++++-- .../hyperv/scripts/attach_disk_drive.ps1 | 19 +++++++++++++------ plugins/providers/hyperv/scripts/new_vhd.ps1 | 5 ++++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 79a35b1bd..ecd1a9d5d 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -37,7 +37,7 @@ module VagrantPlugins # @param [String] controller_location # @param [Hash] opts def attach_disk(disk_file_path, **opts) - execute(:attach_disk_drive, VmId: @vm_id, DiskFilePath: disk_file_path, ControllerType: opts[:ControllerType], + execute(:attach_disk_drive, VmId: @vm_id, Path: disk_file_path, ControllerType: opts[:ControllerType], ControllerNumber: opts[:ControllerNumber], ControllerLocation: opts[:ControllerLocation]) end @@ -48,7 +48,9 @@ module VagrantPlugins # ensure size_bytes is a uint64 execute(:new_vhd, Path: path, SizeBytes: size_bytes, Fixed: opts[:Fixed], BlockSizeBytes: opts[:BlockSizeBytes], LogicalSectorSizeBytes: opts[:LogicalSectorSizeBytes], - PhysicalSectorSizeBytes: opts[:PhsyicalSectorSizeBytes]) + PhysicalSectorSizeBytes: opts[:PhysicalSectorSizeBytes], + SourceDisk: opts[:SourceDisk], Differencing: opts[:Differencing], + ParentPath: opts[:ParentPath]) end # @param [String] controller_type diff --git a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 index 10213c359..64ee1ab27 100644 --- a/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 +++ b/plugins/providers/hyperv/scripts/attach_disk_drive.ps1 @@ -3,18 +3,25 @@ param( [Parameter(Mandatory=$true)] [string]$VmId, + [Parameter(Mandatory=$true)] + [string]$Path, [string]$ControllerType, [string]$ControllerNumber, - [string]$ControllerLocation, - [Parameter(Mandatory=$true)] - [string]$DiskFilePath + [string]$ControllerLocation ) +$Params = @{} + +foreach ($key in $MyInvocation.BoundParameters.keys) { + $value = (Get-Variable -Exclude "ErrorAction" $key).Value + if (($key -ne "VmId") -and ($key -ne "ErrorAction")) { + $Params.Add($key, $value) + } +} + try { $VM = Hyper-V\Get-VM -Id $VmId - #Hyper-V\Add-VMHardDiskDrive -VMName $vm -ControllerType $ControllerType -ControllerNumber $ControllerNumber -ControllerLocation $ControllerLocation -Path $DiskFilePath - # Add logic to support missing params. Below is the simple case for attaching a disk - Hyper-V\Add-VMHardDiskDrive -VMName $VM.Name -Path $DiskFilePath + Hyper-V\Add-VMHardDiskDrive -VMName $VM.Name @Params } catch { Write-ErrorMessage "Failed to attach disk ${DiskFilePath} to VM ${VM}: ${PSItem}" exit 1 diff --git a/plugins/providers/hyperv/scripts/new_vhd.ps1 b/plugins/providers/hyperv/scripts/new_vhd.ps1 index ded00f2f5..c1be12c5f 100644 --- a/plugins/providers/hyperv/scripts/new_vhd.ps1 +++ b/plugins/providers/hyperv/scripts/new_vhd.ps1 @@ -6,9 +6,12 @@ param( [Parameter(Mandatory=$true)] [UInt64]$SizeBytes, [switch]$Fixed, + [switch]$Differencing, + [string]$ParentPath, [string]$BlockSizeBytes, [string]$LogicalSectorSizeBytes, - [string]$PhysicalSectorSizeBytes + [string]$PhysicalSectorSizeBytes, + [UInt64]$SourceDisk ) $Params = @{} From 192caab02d9e5e2a442c396a1e41997097f73d11 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 14:22:11 -0700 Subject: [PATCH 65/97] Fix provider_config merging for disk config --- plugins/kernel_v2/config/disk.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index f4499bdf6..b84e71e3d 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -97,7 +97,11 @@ module VagrantPlugins end current = @provider_config.merge(current) if !@provider_config.empty? - @provider_config = current + if current + @provider_config = current[:provider_config] + else + @provider_config = {} + end end def finalize! @@ -118,13 +122,6 @@ module VagrantPlugins @name = nil end end - - # TODO: fix me?? - if @provider_config.empty? - @provider_config = nil - else - @provider_config = @provider_config[:provider_config] - end end # @return [Array] array of strings of error messages from config option validation From be939fcb59a6608e6f1660b29af9d49e1a526566 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 14:31:12 -0700 Subject: [PATCH 66/97] Remove extra comments --- plugins/providers/hyperv/cap/configure_disks.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 6aecab08f..d8af277d4 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -139,13 +139,6 @@ module VagrantPlugins # Creates and attaches a disk to a machine # - # Extra params: - # - Fixed: true - # - BlockSizeBytes: must be 512 or 4096 - # - LogicalSectorSizeBytes: must be 512 or 4096 - # - PhysicalSectorSizeBytes: must be 512 or 4096 - # - SourceDisk: file path - # # @param [Vagrant::Machine] machine # @param [Kernel_V2::VagrantConfigDisk] disk_config def self.create_disk(machine, disk_config) From cf063c6e38ea0bc79680ce1b5f5b137ff7d8cf02 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 14:53:42 -0700 Subject: [PATCH 67/97] Update validation to look for if provider_config is empty not nil --- plugins/kernel_v2/config/disk.rb | 2 +- test/unit/plugins/kernel_v2/config/disk_test.rb | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index b84e71e3d..6f3b6c6ca 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -184,7 +184,7 @@ module VagrantPlugins end end - if @provider_config + if !@provider_config.empty? if !@provider_config.keys.include?(machine.provider_name) machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider", machine: machine.name, diff --git a/test/unit/plugins/kernel_v2/config/disk_test.rb b/test/unit/plugins/kernel_v2/config/disk_test.rb index ebb0f4103..0d7a39959 100644 --- a/test/unit/plugins/kernel_v2/config/disk_test.rb +++ b/test/unit/plugins/kernel_v2/config/disk_test.rb @@ -9,8 +9,11 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigDisk do subject { described_class.new(type) } + let(:ui) { double("ui") } + let(:env) { double("env", ui: ui) } let(:provider) { double("provider") } - let(:machine) { double("machine", provider: provider, provider_name: :virtualbox) } + let(:machine) { double("machine", name: "name", provider: provider, env: env, + provider_name: :virtualbox) } def assert_invalid From 7012328672b95e607cfdea4decf978d65f3616fa Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 14:53:57 -0700 Subject: [PATCH 68/97] Add hyperv docs for disk management --- .../docs/disks/hyperv/common-issues.html.md | 26 ++++++++++++++ .../source/docs/disks/hyperv/index.html.md | 35 +++++++++++++++++++ .../source/docs/disks/hyperv/usage.html.md | 31 ++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 website/source/docs/disks/hyperv/common-issues.html.md create mode 100644 website/source/docs/disks/hyperv/index.html.md create mode 100644 website/source/docs/disks/hyperv/usage.html.md diff --git a/website/source/docs/disks/hyperv/common-issues.html.md b/website/source/docs/disks/hyperv/common-issues.html.md new file mode 100644 index 000000000..a31a000c6 --- /dev/null +++ b/website/source/docs/disks/hyperv/common-issues.html.md @@ -0,0 +1,26 @@ +--- +layout: "docs" +page_title: "Common Issues - Disks Hyper-V Provider" +sidebar_current: "disks-providers-virtualbox-issues" +description: |- + This page lists some common issues people run into with Vagrant and Hyper-V + as well as solutions for those issues. +--- + +# Common Issues and Troubleshooting + +This page lists some common issues people run into with Vagrant and Hyper-V +as well as solutions for those issues. + +## Are my disks attached? + +A handy way to figure out what disks are attached (or not attached) to your guest +is to open up the Hyper-V GUI and select the guest. When selecting a guest on the GUI, +it should open more information about the guest, including storage information. Here +you should see a list of disks attached to your guest. + +## Applying Vagrant disk configuration changes to guests + +Due to how Hyper-V works, you must reload your guest for any disk config changes +to be applied. So if you update your Vagrantfile to update or even remove disks, make +sure to `vagrant reload` your guests for these changes to be applied. diff --git a/website/source/docs/disks/hyperv/index.html.md b/website/source/docs/disks/hyperv/index.html.md new file mode 100644 index 000000000..99fb27389 --- /dev/null +++ b/website/source/docs/disks/hyperv/index.html.md @@ -0,0 +1,35 @@ +--- +layout: "docs" +page_title: "Disks for Hyper-V Provider" +sidebar_current: "disks-providers-virtualbox" +description: |- + Vagrant comes with support out of the box for Hyper-V, a free, + cross-platform consumer virtualization product. +--- + +# Hyper-V + +
+ Warning! This feature is experimental and may break or + change in between releases. Use at your own risk. It currently is not officially + supported or functional. + + This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to: + + ``` + VAGRANT_EXPERIMENTAL="disks" + ``` + + Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more + information about this flag visit the [Experimental docs page](/docs/experimental/) + for more info. Without this flag enabled, any disks defined will not be configured. +
+ +Because of how Hyper-V handles disk management, a Vagrant guest _must_ be powered +off for any changes to be applied to a guest. If you make a configuration change +with a guests disk, you will need to `vagrant reload` the guest for any changes +to be applied. + +For more information on how to use VirtualBox to configure disks for a guest, refer +to the [general usage](/docs/disks/usage.html) and [configuration](/docs/disks/configuration.html) +guide for more information. diff --git a/website/source/docs/disks/hyperv/usage.html.md b/website/source/docs/disks/hyperv/usage.html.md new file mode 100644 index 000000000..52ee044ab --- /dev/null +++ b/website/source/docs/disks/hyperv/usage.html.md @@ -0,0 +1,31 @@ +--- +layout: "docs" +page_title: "Usage - Disks VirtualBox Provider" +sidebar_current: "disks-providers-virtualbox-usage" +description: |- + The Vagrant VirtualBox provider is used just like any other provider. Please + read the general basic usage page for providers. +--- + +# Usage + +
+ Warning! This feature is experimental and may break or + change in between releases. Use at your own risk. It currently is not officially + supported or functional. + + This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to: + + ``` + VAGRANT_EXPERIMENTAL="disks" + ``` + + Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more + information about this flag visit the [Experimental docs page](/docs/experimental/) + for more info. Without this flag enabled, any disks defined will not be configured. +
+ +For examples of how to use the disk feature with VirtualBox, please refer to the +[general disk usage guide](/docs/disks/usage.html) for more examples. + +## provider_config options From 173d7213368f1142e5cd90ef788ee7e68b60f3f7 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 15:19:30 -0700 Subject: [PATCH 69/97] Add Hyper-V Disk management docs --- website/pages/docs/disks/usage.mdx | 3 -- .../docs/disks/hyperv/common-issues.html.md | 2 +- .../source/docs/disks/hyperv/index.html.md | 2 +- .../source/docs/disks/hyperv/usage.html.md | 50 +++++++++++++++++-- 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/website/pages/docs/disks/usage.mdx b/website/pages/docs/disks/usage.mdx index 3ab962a92..1bedbf6e9 100644 --- a/website/pages/docs/disks/usage.mdx +++ b/website/pages/docs/disks/usage.mdx @@ -21,9 +21,6 @@ Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more information about this flag visit the [Experimental docs page](/docs/experimental/) for more info. Without this flag enabled, any disks defined will not be configured. -Also note that the examples below use the VirtualBox provider, which is the current -supported provider for this feature. - Below are some very simple examples of how to use Vagrant Disks with the VirtualBox provider. ## Basic Examples diff --git a/website/source/docs/disks/hyperv/common-issues.html.md b/website/source/docs/disks/hyperv/common-issues.html.md index a31a000c6..9028985dd 100644 --- a/website/source/docs/disks/hyperv/common-issues.html.md +++ b/website/source/docs/disks/hyperv/common-issues.html.md @@ -1,7 +1,7 @@ --- layout: "docs" page_title: "Common Issues - Disks Hyper-V Provider" -sidebar_current: "disks-providers-virtualbox-issues" +sidebar_current: "disks-providers-hyperv-issues" description: |- This page lists some common issues people run into with Vagrant and Hyper-V as well as solutions for those issues. diff --git a/website/source/docs/disks/hyperv/index.html.md b/website/source/docs/disks/hyperv/index.html.md index 99fb27389..b83640319 100644 --- a/website/source/docs/disks/hyperv/index.html.md +++ b/website/source/docs/disks/hyperv/index.html.md @@ -1,7 +1,7 @@ --- layout: "docs" page_title: "Disks for Hyper-V Provider" -sidebar_current: "disks-providers-virtualbox" +sidebar_current: "disks-providers-hyperv" description: |- Vagrant comes with support out of the box for Hyper-V, a free, cross-platform consumer virtualization product. diff --git a/website/source/docs/disks/hyperv/usage.html.md b/website/source/docs/disks/hyperv/usage.html.md index 52ee044ab..356afcb66 100644 --- a/website/source/docs/disks/hyperv/usage.html.md +++ b/website/source/docs/disks/hyperv/usage.html.md @@ -1,9 +1,9 @@ --- layout: "docs" -page_title: "Usage - Disks VirtualBox Provider" -sidebar_current: "disks-providers-virtualbox-usage" +page_title: "Usage - Disks Hyper-V Provider" +sidebar_current: "disks-providers-hyperv-usage" description: |- - The Vagrant VirtualBox provider is used just like any other provider. Please + The Vagrant Hyper-V provider is used just like any other provider. Please read the general basic usage page for providers. --- @@ -25,7 +25,49 @@ description: |- for more info. Without this flag enabled, any disks defined will not be configured. -For examples of how to use the disk feature with VirtualBox, please refer to the +For examples of how to use the disk feature with Hyper-V, please refer to the [general disk usage guide](/docs/disks/usage.html) for more examples. ## provider_config options + +Most options are used for either creating or attaching a hard disk to your guest. +Vagrant supports most options for these operations. You should be able to define +the powershell specific argument to a given Hyper-V command in the provider_config +hash, and Vagrant should properly pass it along to the command. + +To define a provider specific option, please refer to the [Disk Options documentation page](/docs/disks/configuration.html) for more info. + +### Note about options defined below + +It is possible these options could be out of date or stale. If you happen to see +an option that has changed or is missing from this page, please open an issue +or pull request on Vagrants GitHub page to correct this. + +### New-VHD Supported Options + +For more information about each option, please visit the [New-VHD Hyper-V documentation](https://docs.microsoft.com/en-us/powershell/module/hyper-v/new-vhd?view=win10-ps). + +__Note:__ By default, all Hyper-V disks are defined as a Dynamic virtual hard disk. If you +wish to make the disk a fixed size, you can set the `Fixed` option below when creating +a new disk. + +* `BlockSizeBytes` (string) - Optional argument, i.e. `"128MB"` +* `Differencing` (bool) - If set, the disk will be used to store differencing changes from parent disk (must set `ParentPath`) +* `Fixed` (bool) - If set, the disk will be a fixed size, not dynamically allocated. +* `LogicalSectorSizeBytes` (string) - Optional argument, must be either `"512MB"` or `"4096MB"` +* `ParentPath` (string) - The parent disk path used if a `Differencing` disk is defined +* `PhysicalSectorSizeBytes` (string) - Optional argument, must be either `"512MB"` or `"4096MB"` +* `SourceDisk` (int) - Existing disk to use as a source for the new disk + +### Add-VMHardDiskDrive Supported Options + +For more information about each option, please visit the [Add-VMHardDiskDrive Hyper-V documentation](https://docs.microsoft.com/en-us/powershell/module/hyper-v/add-vmharddiskdrive?view=win10-ps) + +Generally, these options do not need to be set or handled by most users. Only +use these options if you are sure you know what you are doing. Vagrant will +be able to attach disks for you without these options, but they are available +if it is required that you specificy a specific location for a disk. + +* `ControllerLocation` (int) - The location that the disk should be attached to on the controller +* `ControllerNumber` (int) - The controller to use for attaching the disk +* `ControllerType` (string) - The kind of controller to use when attaching the a disk. Only `"IDE"` and `"SCSI"` are valid. From d07e6c5c6a4ff07ae5c32d5adb710390545fb580 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 15:31:41 -0700 Subject: [PATCH 70/97] Rearrange hyperv disk driver methods --- plugins/providers/hyperv/driver.rb | 123 +++++++++++++++-------------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index ecd1a9d5d..521c86fc9 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -28,67 +28,6 @@ module VagrantPlugins @vm_id = id end - # - # Disk Driver methods - # - - # @param [String] controller_type - # @param [String] controller_number - # @param [String] controller_location - # @param [Hash] opts - def attach_disk(disk_file_path, **opts) - execute(:attach_disk_drive, VmId: @vm_id, Path: disk_file_path, ControllerType: opts[:ControllerType], - ControllerNumber: opts[:ControllerNumber], ControllerLocation: opts[:ControllerLocation]) - end - - # @param [String] path - # @param [Int] size_bytes - # @param [Hash] opts - def create_disk(path, size_bytes, **opts) - # ensure size_bytes is a uint64 - execute(:new_vhd, Path: path, SizeBytes: size_bytes, Fixed: opts[:Fixed], - BlockSizeBytes: opts[:BlockSizeBytes], LogicalSectorSizeBytes: opts[:LogicalSectorSizeBytes], - PhysicalSectorSizeBytes: opts[:PhysicalSectorSizeBytes], - SourceDisk: opts[:SourceDisk], Differencing: opts[:Differencing], - ParentPath: opts[:ParentPath]) - end - - # @param [String] controller_type - # @param [String] controller_number - # @param [String] controller_location - # @param [Hash] opts - def remove_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) - execute(:remove_disk_drive, VmId: @vm_id, ControllerType: controller_type, - ControllerNumber: controller_number, ControllerLocation: controller_location, - DiskFilePath: disk_file_path) - end - - # @param [String] path - # @param [Int] size_bytes - # @param [Hash] opts - def resize_disk(disk_file_path, size_bytes, **opts) - execute(:resize_disk_drive, VmId: @vm_id, DiskFilePath: disk_file_path, - DiskSize: size_bytes) - end - - def list_hdds - execute(:list_hdds, VmId: @vm_id) - end - - # @param [String] disk_file_path - def get_disk(disk_file_path) - execute(:get_vhd, DiskFilePath: disk_file_path) - end - - # @param [String] disk_file_path - def dismount_disk(disk_file_path) - execute(:dismount_vhd, DiskFilePath: disk_file_path) - end - - ######## - ######## - ######## - # @return [Boolean] Supports VMCX def has_vmcx_support? !!execute(:has_vmcx_support)["result"] @@ -279,6 +218,68 @@ module VagrantPlugins execute(:set_name, VMID: vm_id, VMName: vmname) end + # + # Disk Driver methods + # + + # @param [String] controller_type + # @param [String] controller_number + # @param [String] controller_location + # @param [Hash] opts + def attach_disk(disk_file_path, **opts) + execute(:attach_disk_drive, VmId: @vm_id, Path: disk_file_path, ControllerType: opts[:ControllerType], + ControllerNumber: opts[:ControllerNumber], ControllerLocation: opts[:ControllerLocation]) + end + + # @param [String] path + # @param [Int] size_bytes + # @param [Hash] opts + def create_disk(path, size_bytes, **opts) + # ensure size_bytes is a uint64 + execute(:new_vhd, Path: path, SizeBytes: size_bytes, Fixed: opts[:Fixed], + BlockSizeBytes: opts[:BlockSizeBytes], LogicalSectorSizeBytes: opts[:LogicalSectorSizeBytes], + PhysicalSectorSizeBytes: opts[:PhysicalSectorSizeBytes], + SourceDisk: opts[:SourceDisk], Differencing: opts[:Differencing], + ParentPath: opts[:ParentPath]) + end + + # @param [String] disk_file_path + def dismount_disk(disk_file_path) + execute(:dismount_vhd, DiskFilePath: disk_file_path) + end + + # @param [String] disk_file_path + def get_disk(disk_file_path) + execute(:get_vhd, DiskFilePath: disk_file_path) + end + + def list_hdds + execute(:list_hdds, VmId: @vm_id) + end + + # @param [String] controller_type + # @param [String] controller_number + # @param [String] controller_location + # @param [Hash] opts + def remove_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) + execute(:remove_disk_drive, VmId: @vm_id, ControllerType: controller_type, + ControllerNumber: controller_number, ControllerLocation: controller_location, + DiskFilePath: disk_file_path) + end + + # @param [String] path + # @param [Int] size_bytes + # @param [Hash] opts + def resize_disk(disk_file_path, size_bytes, **opts) + execute(:resize_disk_drive, VmId: @vm_id, DiskFilePath: disk_file_path, + DiskSize: size_bytes) + end + + ######## + ######## + ######## + + protected def execute_powershell(path, options, &block) From 754928a206bb08f8b4547de4ee7acab88102cc6e Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 15:45:49 -0700 Subject: [PATCH 71/97] Ensure provider_config is a hash before calling .empty? --- plugins/kernel_v2/config/disk.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index 6f3b6c6ca..e1480be24 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -184,11 +184,13 @@ module VagrantPlugins end end - if !@provider_config.empty? - if !@provider_config.keys.include?(machine.provider_name) - machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider", - machine: machine.name, - provider_name: machine.provider_name)) + if @provider_config + if !@provider_config.empty? + if !@provider_config.keys.include?(machine.provider_name) + machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider", + machine: machine.name, + provider_name: machine.provider_name)) + end end end From 43eaceef13b01fb1c0aebef769cce2a8b404ae70 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 17:18:59 -0700 Subject: [PATCH 72/97] Update disk meta keys to be consistent with Hyper-V keys --- plugins/providers/hyperv/cap/cleanup_disks.rb | 9 ++++----- plugins/providers/hyperv/cap/configure_disks.rb | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index cf78e821f..a6d7fbb40 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -29,18 +29,17 @@ module VagrantPlugins disk_meta.each do |d| # look at Path instead of Name or UUID - disk_name = File.basename(d["path"], '.*') + disk_name = File.basename(d["Path"], '.*') dsk = defined_disks.select { |dk| dk.name == disk_name } if !dsk.empty? || d["primary"] == true next else - LOGGER.warn("Found disk not in Vagrantfile config: '#{d["name"]}'. Removing disk from guest #{machine.name}") - disk_info = machine.provider.driver.get_disk(d["path"]) + LOGGER.warn("Found disk not in Vagrantfile config: '#{d["Name"]}'. Removing disk from guest #{machine.name}") - machine.ui.warn("Disk '#{d["name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) + machine.ui.warn("Disk '#{d["Name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) - disk_actual = all_disks.select { |a| a["Path"] == d["path"] }.first + disk_actual = all_disks.select { |a| a["Path"] == d["Path"] }.first machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["ControllerLocation"], disk_actual["Path"]) end diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index d8af277d4..9e0e084f2 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -102,7 +102,7 @@ module VagrantPlugins # LOGGER.info("No further configuration required for disk '#{disk.name}'") #end - disk_metadata = {uuid: current_disk["DiskIdentifier"], name: disk.name, path: current_disk["Path"]} + disk_metadata = {UUID: current_disk["DiskIdentifier"], Name: disk.name, Path: current_disk["Path"]} if disk.primary disk_metadata[:primary] = true end @@ -166,7 +166,7 @@ module VagrantPlugins end disk_info = machine.provider.driver.get_disk(disk_file) - disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} + disk_metadata = {UUID: disk_info["DiskIdentifier"], Name: disk_config.name, Path: disk_info["Path"]} machine.provider.driver.attach_disk(disk_file, disk_provider_config) @@ -224,7 +224,7 @@ module VagrantPlugins disk_info = machine.provider.driver.get_disk(defined_disk["Path"]) # Store updated metadata - disk_metadata = {uuid: disk_info["DiskIdentifier"], name: disk_config.name, path: disk_info["Path"]} + disk_metadata = {UUID: disk_info["DiskIdentifier"], Name: disk_config.name, Path: disk_info["Path"]} disk_metadata end From 234bff9271c87288954b54684247466ebfd216c0 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 17:30:36 -0700 Subject: [PATCH 73/97] Add cleanup_disks_test unit test file --- .../hyperv/cap/cleanup_disks_test.rb | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb index ab1129ccf..be09d60c0 100644 --- a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb @@ -1,3 +1,4 @@ +require_relative "../../../../base" require Vagrant.source_root.join("plugins/providers/hyperv/cap/cleanup_disks") describe VagrantPlugins::HyperV::Cap::CleanupDisks do @@ -33,8 +34,35 @@ describe VagrantPlugins::HyperV::Cap::CleanupDisks do end context "#cleanup_disks" do + it "returns if there's no data in meta file" do + subject.cleanup_disks(machine, defined_disks, disk_meta_file) + expect(subject).not_to receive(:handle_cleanup_disk) + end + + describe "with disks to clean up" do + let(:disk_meta_file) { {disk: [{"UUID"=>"1234", "Path"=> "c:\\users\\vagrant\\storage.vhdx", "Name"=>"storage"}], floppy: [], dvd: []} } + + it "calls the cleanup method if a disk_meta file is defined" do + expect(subject).to receive(:handle_cleanup_disk). + with(machine, defined_disks, disk_meta_file["disk"]). + and_return(true) + + subject.cleanup_disks(machine, defined_disks, disk_meta_file) + end + end end context "#handle_cleanup_disk" do + let(:disk_meta_file) { {disk: [{"UUID"=>"1234", "Path"=> "c:\\users\\vagrant\\storage.vhdx", "Name"=>"storage"}], floppy: [], dvd: []} } + let(:defined_disks) { [] } + let(:all_disks) { [{"UUID"=>"1234", "Path"=> "c:\\users\\vagrant\\storage.vhdx", "Name"=>"storage", + "ControllerType"=>"IDE", "ControllerNumber"=>1, "ControllerLocation"=>0}] } + + it "removes and closes medium from guest" do + expect(driver).to receive(:list_hdds).and_return(all_disks) + expect(driver).to receive(:remove_disk).with("IDE", 1, 0, "c:\\users\\vagrant\\storage.vhdx").and_return(true) + + subject.handle_cleanup_disk(machine, defined_disks, disk_meta_file[:disk]) + end end end From 99d244c4edea39e085bf3fa2a30da93785f52f12 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 21 Apr 2020 17:33:43 -0700 Subject: [PATCH 74/97] Build out initial tests for configure_disks --- .../hyperv/cap/configure_disks_test.rb | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb index fb164e3e2..658be9399 100644 --- a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb @@ -1,3 +1,4 @@ +require_relative "../../../../base" require Vagrant.source_root.join("plugins/providers/hyperv/cap/configure_disks") describe VagrantPlugins::HyperV::Cap::ConfigureDisks do @@ -35,5 +36,51 @@ describe VagrantPlugins::HyperV::Cap::ConfigureDisks do end context "#configure_disks" do + it "configures disks and returns the disks defined" do + end + + describe "with no disks to configure" do + it "returns empty hash if no disks to configure" do + end + end + end + + context "#get_current_disk" do + it "gets primary disk uuid if disk to configure is primary" do + end + + it "finds the disk to configure" do + end + + it "returns nil if disk is not found" do + end + end + + context "#handle_configure_disk" do + describe "when creating a new disk" do + it "creates a new disk if it doesn't yet exist" do + end + end + + describe "when a disk needs to be resized" do + it "resizes a disk" do + end + end + + describe "if no additional disk configuration is required" do + it "does nothing if all disks are properly configured" do + end + end + end + + context "#compare_disk_size" do + end + + context "#create_disk" do + it "creates a disk and attaches it to a guest" do + end + end + + context "#resize_disk" do end end From 56645b7bc5a29801c27529a44a7e7afbe204c402 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 22 Apr 2020 09:29:24 -0700 Subject: [PATCH 75/97] Finish up configure_disk_test unit tests --- .../providers/hyperv/cap/configure_disks.rb | 3 +- .../hyperv/cap/configure_disks_test.rb | 164 ++++++++++++++++++ 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 9e0e084f2..88c4e2ea0 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -146,7 +146,7 @@ module VagrantPlugins disk_provider_config = {} disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config - if !disk_provider_config.empty? + if disk_provider_config disk_provider_config = convert_size_vars!(disk_provider_config) end @@ -155,6 +155,7 @@ module VagrantPlugins if disk_config.file disk_file = disk_config.file + LOGGER.info("Disk already defiend by user at '#{disk_file}'. Using this disk instead of creating a new one...") else # Set the extension disk_ext = disk_config.disk_ext diff --git a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb index 658be9399..6e948b7c0 100644 --- a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb @@ -31,56 +31,220 @@ describe VagrantPlugins::HyperV::Cap::ConfigureDisks do let(:subject) { described_class } + let(:all_disks) { [{"UUID"=>"12345", + "Path"=>"C:/Users/vagrant/disks/ubuntu-18.04-amd64-disk001.vhdx", + "ControllerLocation"=>0, + "ControllerNumber"=>0}, + {"UUID"=>"67890", + "Name"=>"disk-0", + "Path"=>"C:/Users/vagrant/disks/disk-0.vhdx", + "ControllerLocation"=>1, + "ControllerNumber"=>0}, + {"UUID"=>"324bbb53-d5ad-45f8-9bfa-1f2468b199a8", + "Path"=>"C:/Users/vagrant/disks/disk-1.vhdx", + "Name"=>"disk-1", + "ControllerLocation"=>2, + "ControllerNumber"=>0}] } + before do allow(Vagrant::Util::Experimental).to receive(:feature_enabled?).and_return(true) end context "#configure_disks" do + let(:dsk_data) { {"UUID"=>"1234", "Name"=>"disk", "Path"=> "C:/Users/vagrant/storage.vhdx"} } + it "configures disks and returns the disks defined" do + allow(driver).to receive(:list_hdds).and_return([]) + expect(subject).to receive(:handle_configure_disk).exactly(4).and_return(dsk_data) + + subject.configure_disks(machine, defined_disks) end describe "with no disks to configure" do + let(:defined_disks) { {} } it "returns empty hash if no disks to configure" do + expect(subject.configure_disks(machine, defined_disks)).to eq({}) end end end context "#get_current_disk" do it "gets primary disk uuid if disk to configure is primary" do + expect(driver).to receive(:get_disk).with(all_disks.first["Path"]).and_return(all_disks.first) + primary_disk = subject.get_current_disk(machine, defined_disks.first, all_disks) + expect(primary_disk).to eq(all_disks.first) end it "finds the disk to configure" do + disk = subject.get_current_disk(machine, defined_disks[1], all_disks) + expect(disk).to eq(all_disks[1]) end it "returns nil if disk is not found" do + disk = subject.get_current_disk(machine, defined_disks[3], all_disks) + expect(disk).to be_nil end end context "#handle_configure_disk" do describe "when creating a new disk" do + let(:all_disks) { [{"UUID"=>"12345", + "Path"=>"C:/Users/vagrant/disks/ubuntu-18.04-amd64-disk001.vhdx", + "ControllerLocation"=>0, + "ControllerNumber"=>0}] } + + let(:disk_meta) { {"UUID"=>"12345", "Name"=>"vagrant_primary", "Path"=>"C:/Users/vagrant/disks/ubuntu-18.04-amd64-disk001.vhdx" } } + it "creates a new disk if it doesn't yet exist" do + expect(subject).to receive(:create_disk).with(machine, defined_disks[1]) + .and_return(disk_meta) + + subject.handle_configure_disk(machine, defined_disks[1], all_disks) end end describe "when a disk needs to be resized" do + let(:all_disks) { [{"UUID"=>"12345", + "Path"=>"C:/Users/vagrant/disks/ubuntu-18.04-amd64-disk001.vhdx", + "ControllerLocation"=>0, + "ControllerNumber"=>0}, + {"UUID"=>"67890", + "Name"=>"disk-0", + "Path"=>"C:/Users/vagrant/disks/disk-0.vhdx", + "ControllerLocation"=>1, + "ControllerNumber"=>0}, + {"UUID"=>"324bbb53-d5ad-45f8-9bfa-1f2468b199a8", + "Path"=>"C:/Users/vagrant/disks/disk-1.vhdx", + "Name"=>"disk-1", + "ControllerLocation"=>2, + "ControllerNumber"=>0}] } + it "resizes a disk" do + expect(subject).to receive(:get_current_disk). + with(machine, defined_disks[1], all_disks).and_return(all_disks[1]) + + expect(subject).to receive(:compare_disk_size). + with(machine, defined_disks[1], all_disks[1]).and_return(true) + + expect(subject).to receive(:resize_disk). + with(machine, defined_disks[1], all_disks[1]).and_return(true) + + subject.handle_configure_disk(machine, defined_disks[1], all_disks) end end describe "if no additional disk configuration is required" do + let(:all_disks) { [{"UUID"=>"12345", + "Path"=>"C:/Users/vagrant/disks/ubuntu-18.04-amd64-disk001.vhdx", + "ControllerLocation"=>0, + "ControllerNumber"=>0}, + {"UUID"=>"67890", + "Name"=>"disk-0", + "Path"=>"C:/Users/vagrant/disks/disk-0.vhdx", + "ControllerLocation"=>1, + "ControllerNumber"=>0}, + {"UUID"=>"324bbb53-d5ad-45f8-9bfa-1f2468b199a8", + "Path"=>"C:/Users/vagrant/disks/disk-1.vhdx", + "Name"=>"disk-1", + "ControllerLocation"=>2, + "ControllerNumber"=>0}] } + it "does nothing if all disks are properly configured" do + expect(subject).to receive(:get_current_disk). + with(machine, defined_disks[1], all_disks).and_return(all_disks[1]) + + expect(subject).to receive(:compare_disk_size). + with(machine, defined_disks[1], all_disks[1]).and_return(false) + + subject.handle_configure_disk(machine, defined_disks[1], all_disks) end end end context "#compare_disk_size" do + let(:disk_config_small) { double("disk", name: "disk-0", size: 41824.0, primary: false, type: :disk) } + let(:disk_config_large) { double("disk", name: "disk-0", size: 123568719476736.0, primary: false, type: :disk) } + + let(:disk_large) { [{"UUID"=>"12345", + "Path"=>"C:/Users/vagrant/disks/ubuntu-18.04-amd64-disk001.vhdx", + "ControllerLocation"=>0, + "ControllerNumber"=>0}] } + + let(:disk_small) { {"UUID"=>"67890", + "Path"=>"C:/Users/vagrant/disks/small_disk.vhd", + "Size"=>1073741824.0, + "ControllerLocation"=>1, + "ControllerNumber"=>0} } + + it "shows a warning if user attempts to shrink size of a vhd disk" do + expect(machine.ui).to receive(:warn) + expect(driver).to receive(:get_disk).with(all_disks[1]["Path"]).and_return(disk_small) + + expect(subject.compare_disk_size(machine, disk_config_small, all_disks[1])).to be_falsey + end + + it "returns true if requested size is bigger than current size" do + expect(driver).to receive(:get_disk).with(all_disks[2]["Path"]).and_return(disk_small) + expect(subject.compare_disk_size(machine, disk_config_large, all_disks[2])).to be_truthy + end end context "#create_disk" do + let(:disk_provider_config) { {} } + let(:disk_config) { double("disk", name: "disk-0", size: 1073741824.0, + primary: false, type: :disk, disk_ext: "vhdx", + provider_config: disk_provider_config, + file: nil) } + + let(:disk_file) { "C:/Users/vagrant/disks/Virtual Hard Disks/disk-0.vhdx" } + + let(:data_dir) { Pathname.new("C:/Users/vagrant/disks") } + + let(:disk) { {"DiskIdentifier"=>"12345", + "Path"=>"C:/Users/vagrant/disks/Virtual Hard Disks/disk-0.vhdx", + "ControllerLocation"=>1, + "ControllerNumber"=>0} } + it "creates a disk and attaches it to a guest" do + expect(machine).to receive(:data_dir).and_return(data_dir) + expect(driver).to receive(:create_disk).with(disk_file, disk_config.size, nil) + expect(driver).to receive(:get_disk).with(disk_file).and_return(disk) + + expect(driver).to receive(:attach_disk).with(disk_file, nil) + + subject.create_disk(machine, disk_config) + end + end + + context "#convert_size_vars!" do + let(:disk_provider_config) { {BlockSizeBytes: "128MB", LogicalSectorSizeBytes: "512MB", PhysicalSectorSizeBytes: "4096MB" } } + it "converts certain powershell arguments into something usable" do + updated_config = subject.convert_size_vars!(disk_provider_config) + + expect(updated_config[:BlockSizeBytes]).to eq(134217728) + expect(updated_config[:LogicalSectorSizeBytes]).to eq(512) + expect(updated_config[:PhysicalSectorSizeBytes]).to eq(4096) end end context "#resize_disk" do + let(:disk_config) { double("disk", name: "disk-0", size: 1073741824.0, + primary: false, type: :disk, disk_ext: "vhdx", + provider_config: nil, + file: nil) } + + let(:disk) { {"DiskIdentifier"=>"12345", + "Path"=>"C:/Users/vagrant/disks/disk-0.vhdx", + "ControllerLocation"=>1, + "ControllerNumber"=>0} } + + let(:disk_file) { "C:/Users/vagrant/disks/disk-0.vhdx" } + + it "resizes the disk" do + expect(driver).to receive(:get_disk).with(disk_file).and_return(disk) + expect(driver).to receive(:resize_disk).with(disk_file, disk_config.size.to_i).and_return(true) + + subject.resize_disk(machine, disk_config, all_disks[1]) + end end end From f8dfcadb70754b1500add69617830087121767ff Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 22 Apr 2020 15:31:38 -0700 Subject: [PATCH 76/97] Only convert BlockSizeBytes option for Hyper-V disk provider_config --- .../providers/hyperv/cap/configure_disks.rb | 30 ++----------------- .../hyperv/cap/configure_disks_test.rb | 2 +- .../source/docs/disks/hyperv/usage.html.md | 4 +-- 3 files changed, 6 insertions(+), 30 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 88c4e2ea0..1a873da3f 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -181,33 +181,9 @@ module VagrantPlugins # @param [Hash] disk_provider_config # @return [Hash] disk_provider_config def self.convert_size_vars!(disk_provider_config) - conversion_keys = [:BlockSizeBytes, :LogicalSectorSizeBytes, :PhysicalSectorSizeBytes] - - conversion_keys.each do |k| - if disk_provider_config.keys.include?(k) - if k.is_a? Integer - # Assume it is bytes - bytes = disk_provider_config[k] - elsif k == :BlockSizeBytes - bytes = Vagrant::Util::Numeric.string_to_bytes(disk_provider_config[k]) - elsif k == :LogicalSectorSizeBytes || k == :PhysicalSectorSizeBytes - # Logical and Physical can only be these exact values, so converting it - # won't work - case disk_provider_config[k] - when "4096MB" - bytes = 4096 - when "512MB" - bytes = 512 - else - # Their config is wrong - bytes = disk_provider_config[k] - end - else - bytes = disk_provider_config[k] - end - - disk_provider_config[k] = bytes - end + if disk_provider_config.keys.include?(:BlockSizeBytes) + bytes = Vagrant::Util::Numeric.string_to_bytes(disk_provider_config[:BlockSizeBytes]) + disk_provider_config[:BlockSizeBytes] = bytes end disk_provider_config diff --git a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb index 6e948b7c0..815e1079e 100644 --- a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb @@ -217,7 +217,7 @@ describe VagrantPlugins::HyperV::Cap::ConfigureDisks do end context "#convert_size_vars!" do - let(:disk_provider_config) { {BlockSizeBytes: "128MB", LogicalSectorSizeBytes: "512MB", PhysicalSectorSizeBytes: "4096MB" } } + let(:disk_provider_config) { {BlockSizeBytes: "128MB", LogicalSectorSizeBytes: 512, PhysicalSectorSizeBytes: 4096 } } it "converts certain powershell arguments into something usable" do updated_config = subject.convert_size_vars!(disk_provider_config) diff --git a/website/source/docs/disks/hyperv/usage.html.md b/website/source/docs/disks/hyperv/usage.html.md index 356afcb66..94046a50e 100644 --- a/website/source/docs/disks/hyperv/usage.html.md +++ b/website/source/docs/disks/hyperv/usage.html.md @@ -54,9 +54,9 @@ a new disk. * `BlockSizeBytes` (string) - Optional argument, i.e. `"128MB"` * `Differencing` (bool) - If set, the disk will be used to store differencing changes from parent disk (must set `ParentPath`) * `Fixed` (bool) - If set, the disk will be a fixed size, not dynamically allocated. -* `LogicalSectorSizeBytes` (string) - Optional argument, must be either `"512MB"` or `"4096MB"` +* `LogicalSectorSizeBytes` (int) - Optional argument, must be either `512` or `4096` * `ParentPath` (string) - The parent disk path used if a `Differencing` disk is defined -* `PhysicalSectorSizeBytes` (string) - Optional argument, must be either `"512MB"` or `"4096MB"` +* `PhysicalSectorSizeBytes` (string) - Optional argument, must be either `512` or `4096` * `SourceDisk` (int) - Existing disk to use as a source for the new disk ### Add-VMHardDiskDrive Supported Options From 38445935ddf63983c0a50c3f11738ef800d3d85b Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 22 Apr 2020 15:49:49 -0700 Subject: [PATCH 77/97] Ensure params are UInt32 rather than string --- plugins/providers/hyperv/scripts/new_vhd.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/providers/hyperv/scripts/new_vhd.ps1 b/plugins/providers/hyperv/scripts/new_vhd.ps1 index c1be12c5f..a8525928c 100644 --- a/plugins/providers/hyperv/scripts/new_vhd.ps1 +++ b/plugins/providers/hyperv/scripts/new_vhd.ps1 @@ -8,10 +8,10 @@ param( [switch]$Fixed, [switch]$Differencing, [string]$ParentPath, - [string]$BlockSizeBytes, - [string]$LogicalSectorSizeBytes, - [string]$PhysicalSectorSizeBytes, - [UInt64]$SourceDisk + [Uint32]$BlockSizeBytes, + [UInt32]$LogicalSectorSizeBytes, + [UInt32]$PhysicalSectorSizeBytes, + [UInt32]$SourceDisk ) $Params = @{} From 18b9ccd0a5e538c8c0132f2f1221dc7cfacc18d9 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 22 Apr 2020 15:51:45 -0700 Subject: [PATCH 78/97] Remove unused local var --- plugins/providers/hyperv/cap/configure_disks.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 1a873da3f..9ee570956 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -59,8 +59,7 @@ module VagrantPlugins # This is not required for newly created disks, as its metadata is # set when creating and attaching the disk. This is only for the primary # disk, since it already exists. - real_disk_info = machine.provider.driver.get_disk(current_disk["Path"]) - current_disk = real_disk_info + current_disk = machine.provider.driver.get_disk(current_disk["Path"]) else # Hyper-V disk names aren't the actual names of the disk, so we have # to grab the name from the file path instead From 66fe2e28543a9346bb4c1fe3720d454052229bc9 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 30 Apr 2020 13:33:45 -0700 Subject: [PATCH 79/97] Ensure size param is set for a disk --- plugins/kernel_v2/config/disk.rb | 9 +++++---- test/unit/plugins/kernel_v2/config/disk_test.rb | 10 ++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index e1480be24..95b8005f3 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -169,12 +169,13 @@ module VagrantPlugins if @size.is_a?(String) @size = Vagrant::Util::Numeric.string_to_bytes(@size) end - - if !@size - errors << I18n.t("vagrant.config.disk.invalid_size", name: @name, machine: machine.name) - end end + if !@size + errors << I18n.t("vagrant.config.disk.invalid_size", name: @name, machine: machine.name) + end + + if @file if !@file.is_a?(String) errors << I18n.t("vagrant.config.disk.invalid_file_type", file: @file, machine: machine.name) diff --git a/test/unit/plugins/kernel_v2/config/disk_test.rb b/test/unit/plugins/kernel_v2/config/disk_test.rb index 0d7a39959..cb37ead49 100644 --- a/test/unit/plugins/kernel_v2/config/disk_test.rb +++ b/test/unit/plugins/kernel_v2/config/disk_test.rb @@ -56,6 +56,16 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigDisk do end end + describe "with an invalid config" do + let(:invalid_subject) { described_class.new(type) } + + it "raises an error if size not set" do + invalid_subject.name = "bar" + subject.finalize! + assert_invalid + end + end + describe "defining a new config that needs to match internal restraints" do before do end From 4130cfe4976d68b6883057259078a378deb7e144 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Fri, 1 May 2020 11:17:27 -0700 Subject: [PATCH 80/97] Properly check for disk paths when cleaning up disks in hyper-v --- plugins/providers/hyperv/cap/cleanup_disks.rb | 11 +++++--- .../providers/virtualbox/cap/cleanup_disks.rb | 2 +- templates/locales/en.yml | 5 ++++ .../hyperv/cap/cleanup_disks_test.rb | 28 +++++++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/plugins/providers/hyperv/cap/cleanup_disks.rb b/plugins/providers/hyperv/cap/cleanup_disks.rb index a6d7fbb40..5ace44221 100644 --- a/plugins/providers/hyperv/cap/cleanup_disks.rb +++ b/plugins/providers/hyperv/cap/cleanup_disks.rb @@ -37,11 +37,14 @@ module VagrantPlugins else LOGGER.warn("Found disk not in Vagrantfile config: '#{d["Name"]}'. Removing disk from guest #{machine.name}") - machine.ui.warn("Disk '#{d["Name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) + machine.ui.warn(I18n.t("vagrant.cap.cleanup_disks.disk_cleanup", name: d["Name"]), prefix: true) - disk_actual = all_disks.select { |a| a["Path"] == d["Path"] }.first - - machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["ControllerLocation"], disk_actual["Path"]) + disk_actual = all_disks.select { |a| File.realdirpath(a["Path"]) == File.realdirpath(d["Path"]) }.first + if !disk_actual + machine.ui.warn(I18n.t("vagrant.cap.cleanup_disks.disk_not_found", name: d["Name"]), prefix: true) + else + machine.provider.driver.remove_disk(disk_actual["ControllerType"], disk_actual["ControllerNumber"], disk_actual["ControllerLocation"], disk_actual["Path"]) + end end end end diff --git a/plugins/providers/virtualbox/cap/cleanup_disks.rb b/plugins/providers/virtualbox/cap/cleanup_disks.rb index d9e11f7ff..5d1029be5 100644 --- a/plugins/providers/virtualbox/cap/cleanup_disks.rb +++ b/plugins/providers/virtualbox/cap/cleanup_disks.rb @@ -36,7 +36,7 @@ module VagrantPlugins LOGGER.warn("Found disk not in Vagrantfile config: '#{d["name"]}'. Removing disk from guest #{machine.name}") disk_info = machine.provider.driver.get_port_and_device(d["uuid"]) - machine.ui.warn("Disk '#{d["name"]}' no longer exists in Vagrant config. Removing and closing medium from guest...", prefix: true) + machine.ui.warn(I18n.t("vagrant.cap.cleanup_disks.disk_cleanup", name: d["name"]), prefix: true) if disk_info.empty? LOGGER.warn("Disk '#{d["name"]}' not attached to guest, but still exists.") diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 985006e0d..0a7a76239 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -2208,6 +2208,11 @@ en: # Translations for Vagrant middleware actions #------------------------------------------------------------------------------- cap: + cleanup_disks: + disk_cleanup: |- + Disk '%{name}' no longer exists in Vagrant config. Removing and closing medium from guest... + disk_not_found: |- + Disk '%{name}' could not be found, and could not be properly removed. Please remove this disk manually if it still exists configure_disks: start: "Configuring storage mediums..." floppy_not_supported: "Floppy disk configuration not yet supported. Skipping disk '%{name}'..." diff --git a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb index be09d60c0..383005f32 100644 --- a/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/cleanup_disks_test.rb @@ -57,6 +57,7 @@ describe VagrantPlugins::HyperV::Cap::CleanupDisks do let(:defined_disks) { [] } let(:all_disks) { [{"UUID"=>"1234", "Path"=> "c:\\users\\vagrant\\storage.vhdx", "Name"=>"storage", "ControllerType"=>"IDE", "ControllerNumber"=>1, "ControllerLocation"=>0}] } + let(:path) { "C:\\Users\\vagrant\\storage.vhdx" } it "removes and closes medium from guest" do expect(driver).to receive(:list_hdds).and_return(all_disks) @@ -64,5 +65,32 @@ describe VagrantPlugins::HyperV::Cap::CleanupDisks do subject.handle_cleanup_disk(machine, defined_disks, disk_meta_file[:disk]) end + + it "displays a warning if the disk could not be determined" do + expect(driver).to receive(:list_hdds).and_return(all_disks) + expect(File).to receive(:realdirpath).and_return(path) + expect(File).to receive(:realdirpath).and_return("") + expect(driver).not_to receive(:remove_disk) + expect(machine.ui).to receive(:warn).twice + + subject.handle_cleanup_disk(machine, defined_disks, disk_meta_file[:disk]) + end + + describe "when windows paths mix cases" do + let(:disk_meta_file) { {disk: [{"UUID"=>"1234", "Path"=> "c:\\users\\vagrant\\storage.vhdx", "Name"=>"storage"}], floppy: [], dvd: []} } + let(:defined_disks) { [] } + let(:all_disks) { [{"UUID"=>"1234", "Path"=> "C:\\Users\\vagrant\\storage.vhdx", "Name"=>"storage", + "ControllerType"=>"IDE", "ControllerNumber"=>1, "ControllerLocation"=>0}] } + + let(:path) { "C:\\Users\\vagrant\\storage.vhdx" } + + it "still removes and closes the medium from the guest" do + expect(driver).to receive(:list_hdds).and_return(all_disks) + expect(File).to receive(:realdirpath).twice.and_return(path) + expect(driver).to receive(:remove_disk).with("IDE", 1, 0, path).and_return(true) + + subject.handle_cleanup_disk(machine, defined_disks, disk_meta_file[:disk]) + end + end end end From 96d19264b6f67848ab76c059fdbfad6f3040789e Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Fri, 1 May 2020 15:17:53 -0700 Subject: [PATCH 81/97] Automatically remove invalid file characters for disk name This commit copies what Vagrant does to filter out guest names with invalid characters, and applies the same regex to disk names. --- plugins/kernel_v2/config/disk.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index 95b8005f3..f8bff732b 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -12,6 +12,8 @@ module VagrantPlugins DEFAULT_DISK_TYPES = [:disk, :dvd, :floppy].freeze + FILE_CHAR_REGEX = /[^-a-z0-9_]/i.freeze + # Note: This value is for internal use only # # @return [String] @@ -115,7 +117,10 @@ module VagrantPlugins @primary = false end - if @name == UNSET_VALUE + if @name.is_a?(String) && @name.match(FILE_CHAR_REGEX) + @logger.warn("Vagrant will remove detected invalid characters in '#{@name}' and convert the disk name into something usable for a file") + @name.gsub!(FILE_CHAR_REGEX, "") + elsif @name == UNSET_VALUE if @primary @name = "vagrant_primary" else From c063ca6100f2f6274ffe5580e81eb5387496b8a6 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 13 May 2020 14:19:28 -0700 Subject: [PATCH 82/97] Replace invalid disk name characters with underscore --- plugins/kernel_v2/config/disk.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index f8bff732b..6d95c750a 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -119,7 +119,7 @@ module VagrantPlugins if @name.is_a?(String) && @name.match(FILE_CHAR_REGEX) @logger.warn("Vagrant will remove detected invalid characters in '#{@name}' and convert the disk name into something usable for a file") - @name.gsub!(FILE_CHAR_REGEX, "") + @name.gsub!(FILE_CHAR_REGEX, "_") elsif @name == UNSET_VALUE if @primary @name = "vagrant_primary" From 71f6b97153021622208e995e07c9f232f5c94a85 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 13 May 2020 14:52:38 -0700 Subject: [PATCH 83/97] Delete old comments --- plugins/providers/hyperv/driver.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 521c86fc9..ba81bdce3 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -235,7 +235,6 @@ module VagrantPlugins # @param [Int] size_bytes # @param [Hash] opts def create_disk(path, size_bytes, **opts) - # ensure size_bytes is a uint64 execute(:new_vhd, Path: path, SizeBytes: size_bytes, Fixed: opts[:Fixed], BlockSizeBytes: opts[:BlockSizeBytes], LogicalSectorSizeBytes: opts[:LogicalSectorSizeBytes], PhysicalSectorSizeBytes: opts[:PhysicalSectorSizeBytes], @@ -275,11 +274,6 @@ module VagrantPlugins DiskSize: size_bytes) end - ######## - ######## - ######## - - protected def execute_powershell(path, options, &block) From a279f89d29e4a8d924cc6f18306221fce8fef5ac Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Wed, 13 May 2020 14:52:50 -0700 Subject: [PATCH 84/97] update how value is checked for execute in hyper-v driver --- plugins/providers/hyperv/driver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index ba81bdce3..99cb7ce13 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -283,7 +283,7 @@ module VagrantPlugins options = options || {} ps_options = [] options.each do |key, value| - next if value == '' || value.nil? + next if !value || value.to_s.empty? next if value == false ps_options << "-#{key}" # If the value is a TrueClass assume switch From ae0fb6f857bee8274e4f01a0fda8456431aeeef4 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 18 May 2020 14:14:14 -0700 Subject: [PATCH 85/97] Update check for provider_config availability --- plugins/providers/hyperv/cap/configure_disks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 9ee570956..f73753c15 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -144,8 +144,8 @@ module VagrantPlugins machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name)) disk_provider_config = {} disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config - - if disk_provider_config + # Convert any shortcut options for powershell commands + if !disk_provider_config.empty? disk_provider_config = convert_size_vars!(disk_provider_config) end From 69dff3a4c8aa7e3c5d77317336f99e9cb93636a2 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 18 May 2020 14:48:13 -0700 Subject: [PATCH 86/97] Use key? helper --- plugins/providers/hyperv/cap/configure_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index f73753c15..db58cfc73 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -180,7 +180,7 @@ module VagrantPlugins # @param [Hash] disk_provider_config # @return [Hash] disk_provider_config def self.convert_size_vars!(disk_provider_config) - if disk_provider_config.keys.include?(:BlockSizeBytes) + if disk_provider_config.key?(:BlockSizeBytes) bytes = Vagrant::Util::Numeric.string_to_bytes(disk_provider_config[:BlockSizeBytes]) disk_provider_config[:BlockSizeBytes] = bytes end From 1579ac9c3a15ac4c23178c862bf57f4376ff3672 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 18 May 2020 14:55:56 -0700 Subject: [PATCH 87/97] Update method docs to include expected opts keys --- plugins/providers/hyperv/driver.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 99cb7ce13..751de4bf0 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -226,6 +226,9 @@ module VagrantPlugins # @param [String] controller_number # @param [String] controller_location # @param [Hash] opts + # @option opts [String] :ControllerType + # @option opts [String] :ControllerNumber + # @option opts [String] :ControllerLocation def attach_disk(disk_file_path, **opts) execute(:attach_disk_drive, VmId: @vm_id, Path: disk_file_path, ControllerType: opts[:ControllerType], ControllerNumber: opts[:ControllerNumber], ControllerLocation: opts[:ControllerLocation]) @@ -234,6 +237,13 @@ module VagrantPlugins # @param [String] path # @param [Int] size_bytes # @param [Hash] opts + # @option opts [Bool] :Fixed + # @option opts [String] :BlockSizeBytes + # @option opts [String] :LogicalSectorSizeBytes + # @option opts [String] :PhysicalSectorSizeBytes + # @option opts [String] :SourceDisk + # @option opts [Bool] :Differencing + # @option opts [String] :ParentPath def create_disk(path, size_bytes, **opts) execute(:new_vhd, Path: path, SizeBytes: size_bytes, Fixed: opts[:Fixed], BlockSizeBytes: opts[:BlockSizeBytes], LogicalSectorSizeBytes: opts[:LogicalSectorSizeBytes], @@ -259,7 +269,11 @@ module VagrantPlugins # @param [String] controller_type # @param [String] controller_number # @param [String] controller_location + # @param [String] disk_file_path # @param [Hash] opts + # @option opts [String] :ControllerType + # @option opts [String] :ControllerNumber + # @option opts [String] :ControllerLocation def remove_disk(controller_type, controller_number, controller_location, disk_file_path, **opts) execute(:remove_disk_drive, VmId: @vm_id, ControllerType: controller_type, ControllerNumber: controller_number, ControllerLocation: controller_location, From 13c91d68a6a37fcb5bba18a76ccaedb15dc24b28 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 18 May 2020 15:10:53 -0700 Subject: [PATCH 88/97] Only grab provider_config if provider key exists and config isn't empty --- plugins/providers/hyperv/cap/configure_disks.rb | 7 +++++-- .../plugins/providers/hyperv/cap/configure_disks_test.rb | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index db58cfc73..e2db93d26 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -143,8 +143,11 @@ module VagrantPlugins def self.create_disk(machine, disk_config) machine.ui.detail(I18n.t("vagrant.cap.configure_disks.create_disk", name: disk_config.name)) disk_provider_config = {} - disk_provider_config = disk_config.provider_config[:hyperv] if disk_config.provider_config - # Convert any shortcut options for powershell commands + + if disk_config.provider_config && disk_config.provider_config.key?(:hyperv) + disk_provider_config = disk_config.provider_config[:hyperv] + end + if !disk_provider_config.empty? disk_provider_config = convert_size_vars!(disk_provider_config) end diff --git a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb index 815e1079e..af51f645e 100644 --- a/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb +++ b/test/unit/plugins/providers/hyperv/cap/configure_disks_test.rb @@ -207,10 +207,10 @@ describe VagrantPlugins::HyperV::Cap::ConfigureDisks do it "creates a disk and attaches it to a guest" do expect(machine).to receive(:data_dir).and_return(data_dir) - expect(driver).to receive(:create_disk).with(disk_file, disk_config.size, nil) + expect(driver).to receive(:create_disk).with(disk_file, disk_config.size, {}) expect(driver).to receive(:get_disk).with(disk_file).and_return(disk) - expect(driver).to receive(:attach_disk).with(disk_file, nil) + expect(driver).to receive(:attach_disk).with(disk_file, {}) subject.create_disk(machine, disk_config) end From b36db04b3d9b2d46a0147e4883300e0ae6584599 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Mon, 18 May 2020 17:21:19 -0700 Subject: [PATCH 89/97] Validate and get default disk extensions for provider This commit updates the hyperv and virtualbox provider caps to validate and also return the default disk extension. --- plugins/kernel_v2/config/disk.rb | 15 +++++---------- plugins/providers/hyperv/cap/validate_disk_ext.rb | 13 ++++++++++--- plugins/providers/hyperv/plugin.rb | 7 ++++++- .../providers/virtualbox/cap/validate_disk_ext.rb | 13 ++++++++++--- plugins/providers/virtualbox/plugin.rb | 7 ++++++- test/unit/plugins/kernel_v2/config/disk_test.rb | 15 ++++++++++++--- 6 files changed, 49 insertions(+), 21 deletions(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index 6d95c750a..b38858475 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -132,7 +132,6 @@ module VagrantPlugins # @return [Array] array of strings of error messages from config option validation def validate(machine) errors = _detected_errors - # validate type with list of known disk types if !DEFAULT_DISK_TYPES.include?(@type) @@ -141,14 +140,10 @@ module VagrantPlugins end if @disk_ext == UNSET_VALUE - # Work around to finalize disk_ext with a valid default per-provider - if machine.provider_name == :virtualbox - @disk_ext = "vdi" - elsif machine.provider_name == :vmware_desktop - @disk_ext = "vmdk" - elsif machine.provider_name == :hyperv - @disk_ext = "vhdx" + if machine.provider.capability?(:set_default_disk_ext) + @disk_ext = machine.provider.capability(:set_default_disk_ext) else + @logger.warn("No provider capability defined to set default 'disk_ext' type. Will use 'vdi' for disk extension.") @disk_ext = "vdi" end elsif @disk_ext @@ -156,8 +151,8 @@ module VagrantPlugins if machine.provider.capability?(:validate_disk_ext) if !machine.provider.capability(:validate_disk_ext, @disk_ext) - if machine.provider.capability?(:get_default_disk_ext) - disk_exts = machine.provider.capability(:get_default_disk_ext).join(', ') + if machine.provider.capability?(:default_disk_exts) + disk_exts = machine.provider.capability(:default_disk_exts).join(', ') else disk_exts = "not found" end diff --git a/plugins/providers/hyperv/cap/validate_disk_ext.rb b/plugins/providers/hyperv/cap/validate_disk_ext.rb index 92e467f51..74512094a 100644 --- a/plugins/providers/hyperv/cap/validate_disk_ext.rb +++ b/plugins/providers/hyperv/cap/validate_disk_ext.rb @@ -7,18 +7,25 @@ module VagrantPlugins LOGGER = Log4r::Logger.new("vagrant::plugins::hyperv::validate_disk_ext") # The default set of disk formats that Hyper-V supports - DEFAULT_DISK_EXT = ["vhd", "vhdx"].map(&:freeze).freeze + DEFAULT_DISK_EXT_LIST = ["vhd", "vhdx"].map(&:freeze).freeze + DEFAULT_DISK_EXT = "vhdx".freeze # @param [Vagrant::Machine] machine # @param [String] disk_ext # @return [Bool] def self.validate_disk_ext(machine, disk_ext) - DEFAULT_DISK_EXT.include?(disk_ext) + DEFAULT_DISK_EXT_LIST.include?(disk_ext) end # @param [Vagrant::Machine] machine # @return [Array] - def self.get_default_disk_ext(machine) + def self.default_disk_exts(machine) + DEFAULT_DISK_EXT_LIST + end + + # @param [Vagrant::Machine] machine + # @return [String] + def self.set_default_disk_ext(machine) DEFAULT_DISK_EXT end end diff --git a/plugins/providers/hyperv/plugin.rb b/plugins/providers/hyperv/plugin.rb index cdf88d7e3..c7d6eb2b9 100644 --- a/plugins/providers/hyperv/plugin.rb +++ b/plugins/providers/hyperv/plugin.rb @@ -47,7 +47,12 @@ module VagrantPlugins Cap::ValidateDiskExt end - provider_capability(:hyperv, :get_default_disk_ext) do + provider_capability(:hyperv, :default_disk_exts) do + require_relative "cap/validate_disk_ext" + Cap::ValidateDiskExt + end + + provider_capability(:hyperv, :set_default_disk_ext) do require_relative "cap/validate_disk_ext" Cap::ValidateDiskExt end diff --git a/plugins/providers/virtualbox/cap/validate_disk_ext.rb b/plugins/providers/virtualbox/cap/validate_disk_ext.rb index e820c39ab..f5da4e8b4 100644 --- a/plugins/providers/virtualbox/cap/validate_disk_ext.rb +++ b/plugins/providers/virtualbox/cap/validate_disk_ext.rb @@ -7,18 +7,25 @@ module VagrantPlugins LOGGER = Log4r::Logger.new("vagrant::plugins::virtualbox::validate_disk_ext") # The default set of disk formats that VirtualBox supports - DEFAULT_DISK_EXT = ["vdi", "vmdk", "vhd"].map(&:freeze).freeze + DEFAULT_DISK_EXT_LIST = ["vdi", "vmdk", "vhd"].map(&:freeze).freeze + DEFAULT_DISK_EXT = "vdi".freeze # @param [Vagrant::Machine] machine # @param [String] disk_ext # @return [Bool] def self.validate_disk_ext(machine, disk_ext) - DEFAULT_DISK_EXT.include?(disk_ext) + DEFAULT_DISK_EXT_LIST.include?(disk_ext) end # @param [Vagrant::Machine] machine # @return [Array] - def self.get_default_disk_ext(machine) + def self.default_disk_exts(machine) + DEFAULT_DISK_EXT_LIST + end + + # @param [Vagrant::Machine] machine + # @return [String] + def self.set_default_disk_ext(machine) DEFAULT_DISK_EXT end end diff --git a/plugins/providers/virtualbox/plugin.rb b/plugins/providers/virtualbox/plugin.rb index 9cb46b54e..63f6a0e21 100644 --- a/plugins/providers/virtualbox/plugin.rb +++ b/plugins/providers/virtualbox/plugin.rb @@ -54,7 +54,12 @@ module VagrantPlugins Cap::ValidateDiskExt end - provider_capability(:virtualbox, :get_default_disk_ext) do + provider_capability(:virtualbox, :default_disk_exts) do + require_relative "cap/validate_disk_ext" + Cap::ValidateDiskExt + end + + provider_capability(:virtualbox, :set_default_disk_ext) do require_relative "cap/validate_disk_ext" Cap::ValidateDiskExt end diff --git a/test/unit/plugins/kernel_v2/config/disk_test.rb b/test/unit/plugins/kernel_v2/config/disk_test.rb index cb37ead49..967a9046d 100644 --- a/test/unit/plugins/kernel_v2/config/disk_test.rb +++ b/test/unit/plugins/kernel_v2/config/disk_test.rb @@ -37,6 +37,8 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigDisk do subject.size = 100 allow(provider).to receive(:capability?).with(:validate_disk_ext).and_return(true) allow(provider).to receive(:capability).with(:validate_disk_ext, "vdi").and_return(true) + allow(provider).to receive(:capability?).with(:set_default_disk_ext).and_return(true) + allow(provider).to receive(:capability).with(:set_default_disk_ext).and_return("vdi") end describe "with defaults" do @@ -64,10 +66,17 @@ describe VagrantPlugins::Kernel_V2::VagrantConfigDisk do subject.finalize! assert_invalid end - end - describe "defining a new config that needs to match internal restraints" do - before do + context "with an invalid disk extension" do + before do + allow(provider).to receive(:capability?).with(:validate_disk_ext).and_return(true) + allow(provider).to receive(:capability).with(:validate_disk_ext, "fake").and_return(false) + end + + it "raises an error" do + subject.finalize! + assert_invalid + end end end end From d35feb62a3eeba56583369c0a240b086d7e1c92a Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 19 May 2020 09:16:03 -0700 Subject: [PATCH 90/97] Simplify key check for provider option config --- plugins/kernel_v2/config/disk.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/kernel_v2/config/disk.rb b/plugins/kernel_v2/config/disk.rb index b38858475..87c3d5741 100644 --- a/plugins/kernel_v2/config/disk.rb +++ b/plugins/kernel_v2/config/disk.rb @@ -187,7 +187,7 @@ module VagrantPlugins if @provider_config if !@provider_config.empty? - if !@provider_config.keys.include?(machine.provider_name) + if !@provider_config.key?(machine.provider_name) machine.env.ui.warn(I18n.t("vagrant.config.disk.missing_provider", machine: machine.name, provider_name: machine.provider_name)) From af20d4a426965e523f80c191c2533a9504d1ef8e Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 19 May 2020 09:19:16 -0700 Subject: [PATCH 91/97] Remove old comment --- plugins/providers/hyperv/cap/configure_disks.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index e2db93d26..1a335d8d0 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -88,19 +88,6 @@ module VagrantPlugins elsif compare_disk_size(machine, disk, current_disk) disk_metadata = resize_disk(machine, disk, current_disk) else - # TODO OLD: What if it needs to be resized? - - # Can't use "attached" attribute, because it is false when the guest - # is powered off - # - #disk_info = machine.provider.driver.get_disk(current_disk["Path"]) - #if disk_info["Attached"] == false - # LOGGER.warn("Disk '#{disk.name}' is not connected to guest '#{machine.name}', Vagrant will attempt to connect disk to guest") - # machine.provider.driver.attach_disk(nil, nil, nil, current_disk["Path"]) - #else - # LOGGER.info("No further configuration required for disk '#{disk.name}'") - #end - disk_metadata = {UUID: current_disk["DiskIdentifier"], Name: disk.name, Path: current_disk["Path"]} if disk.primary disk_metadata[:primary] = true From 497cb67b505ebe462882c770d1b872149eb98256 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 19 May 2020 09:34:37 -0700 Subject: [PATCH 92/97] Include new disk ext cap methods in test mock ups --- test/unit/plugins/kernel_v2/config/vm_test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unit/plugins/kernel_v2/config/vm_test.rb b/test/unit/plugins/kernel_v2/config/vm_test.rb index c6e26ff9c..c6576df6a 100644 --- a/test/unit/plugins/kernel_v2/config/vm_test.rb +++ b/test/unit/plugins/kernel_v2/config/vm_test.rb @@ -40,6 +40,8 @@ describe VagrantPlugins::Kernel_V2::VMConfig do allow(provider).to receive(:capability?).with(:validate_disk_ext).and_return(true) allow(provider).to receive(:capability).with(:validate_disk_ext, "vdi").and_return(true) + allow(provider).to receive(:capability?).with(:set_default_disk_ext).and_return(true) + allow(provider).to receive(:capability).with(:set_default_disk_ext).and_return("vdi") subject.box = "foo" end From 9c1338b33547026d52903c80f5a7f0f784743a2f Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 26 May 2020 11:04:53 -0700 Subject: [PATCH 93/97] Fix typo in logger message --- plugins/providers/hyperv/cap/configure_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 1a335d8d0..71128ca44 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -144,7 +144,7 @@ module VagrantPlugins if disk_config.file disk_file = disk_config.file - LOGGER.info("Disk already defiend by user at '#{disk_file}'. Using this disk instead of creating a new one...") + LOGGER.info("Disk already defined by user at '#{disk_file}'. Using this disk instead of creating a new one...") else # Set the extension disk_ext = disk_config.disk_ext From 05d3045f3af63da210a155366f2e6302b5302b9b Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 26 May 2020 11:08:02 -0700 Subject: [PATCH 94/97] Add RDoc for list_hdds --- plugins/providers/hyperv/driver.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/providers/hyperv/driver.rb b/plugins/providers/hyperv/driver.rb index 751de4bf0..0b281eb3f 100644 --- a/plugins/providers/hyperv/driver.rb +++ b/plugins/providers/hyperv/driver.rb @@ -262,6 +262,7 @@ module VagrantPlugins execute(:get_vhd, DiskFilePath: disk_file_path) end + # @return [Array[Hash]] def list_hdds execute(:list_hdds, VmId: @vm_id) end From 39b5bb4beb743147ed8c6626b576fe83cdf7cc47 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 26 May 2020 13:16:48 -0700 Subject: [PATCH 95/97] Simplify selecting disk from all_disks hash --- plugins/providers/hyperv/cap/configure_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 71128ca44..152042354 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -52,7 +52,7 @@ module VagrantPlugins # We can't rely on the order of `all_disks`, as they will not # always come in port order, but primary should always be Location 0 Number 0. - current_disk = all_disks.select { |d| d["ControllerLocation"] == 0 && d["ControllerNumber"] == 0 }.first + current_disk = all_disks.detect { |d| d["ControllerLocation"] == 0 && d["ControllerNumber"] == 0 } # Need to get actual disk info to obtain UUID instead of what's returned # From 0139d8f020bc3476136b544411ad98176274bb46 Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Tue, 26 May 2020 13:17:16 -0700 Subject: [PATCH 96/97] Simplify other select to detect instead --- plugins/providers/hyperv/cap/configure_disks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/providers/hyperv/cap/configure_disks.rb b/plugins/providers/hyperv/cap/configure_disks.rb index 152042354..e7d5fe96a 100644 --- a/plugins/providers/hyperv/cap/configure_disks.rb +++ b/plugins/providers/hyperv/cap/configure_disks.rb @@ -63,7 +63,7 @@ module VagrantPlugins else # Hyper-V disk names aren't the actual names of the disk, so we have # to grab the name from the file path instead - current_disk = all_disks.select { |d| File.basename(d["Path"], '.*') == disk.name}.first + current_disk = all_disks.detect { |d| File.basename(d["Path"], '.*') == disk.name} end current_disk From 89678950ae890499af50d02455472ce1db07a70f Mon Sep 17 00:00:00 2001 From: Brian Cain Date: Thu, 4 Jun 2020 13:20:00 -0700 Subject: [PATCH 97/97] Update hyper-v website docs for new website format --- website/data/docs-navigation.js | 1 + .../docs/disks/hyperv/common-issues.mdx} | 6 ++-- website/pages/docs/disks/hyperv/index.mdx | 33 +++++++++++++++++ .../docs/disks/hyperv/usage.mdx} | 32 ++++++++--------- .../source/docs/disks/hyperv/index.html.md | 35 ------------------- 5 files changed, 52 insertions(+), 55 deletions(-) rename website/{source/docs/disks/hyperv/common-issues.html.md => pages/docs/disks/hyperv/common-issues.mdx} (88%) create mode 100644 website/pages/docs/disks/hyperv/index.mdx rename website/{source/docs/disks/hyperv/usage.html.md => pages/docs/disks/hyperv/usage.mdx} (75%) delete mode 100644 website/source/docs/disks/hyperv/index.html.md diff --git a/website/data/docs-navigation.js b/website/data/docs-navigation.js index 5a8ff9137..3c6e9e72e 100644 --- a/website/data/docs-navigation.js +++ b/website/data/docs-navigation.js @@ -119,6 +119,7 @@ export default [ 'configuration', 'usage', { category: 'virtualbox', content: ['usage', 'common-issues'] }, + { category: 'hyperv', content: ['usage', 'common-issues'] }, ], }, 'multi-machine', diff --git a/website/source/docs/disks/hyperv/common-issues.html.md b/website/pages/docs/disks/hyperv/common-issues.mdx similarity index 88% rename from website/source/docs/disks/hyperv/common-issues.html.md rename to website/pages/docs/disks/hyperv/common-issues.mdx index 9028985dd..467a276cc 100644 --- a/website/source/docs/disks/hyperv/common-issues.html.md +++ b/website/pages/docs/disks/hyperv/common-issues.mdx @@ -1,7 +1,7 @@ --- -layout: "docs" -page_title: "Common Issues - Disks Hyper-V Provider" -sidebar_current: "disks-providers-hyperv-issues" +layout: docs +page_title: Common Issues - Disks Hyper-V Provider +sidebar_title: Common Issues description: |- This page lists some common issues people run into with Vagrant and Hyper-V as well as solutions for those issues. diff --git a/website/pages/docs/disks/hyperv/index.mdx b/website/pages/docs/disks/hyperv/index.mdx new file mode 100644 index 000000000..c64998b21 --- /dev/null +++ b/website/pages/docs/disks/hyperv/index.mdx @@ -0,0 +1,33 @@ +--- +layout: docs +page_title: Disks for Hyper-V Provider +sidebar_title: Hyper-V +description: |- + Vagrant comes with support out of the box for Hyper-V, a free, + cross-platform consumer virtualization product. +--- + +# Hyper-V + +~> **Warning!** This feature is experimental and may break or +change in between releases. Use at your own risk. It currently is not officially +supported or functional. + +This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to: + +``` +VAGRANT_EXPERIMENTAL="disks" +``` + +Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more +information about this flag visit the [Experimental docs page](/docs/experimental/) +for more info. Without this flag enabled, any disks defined will not be configured. + +Because of how Hyper-V handles disk management, a Vagrant guest _must_ be powered +off for any changes to be applied to a guest. If you make a configuration change +with a guests disk, you will need to `vagrant reload` the guest for any changes +to be applied. + +For more information on how to use VirtualBox to configure disks for a guest, refer +to the [general usage](/docs/disks/usage) and [configuration](/docs/disks/configuration) +guide for more information. diff --git a/website/source/docs/disks/hyperv/usage.html.md b/website/pages/docs/disks/hyperv/usage.mdx similarity index 75% rename from website/source/docs/disks/hyperv/usage.html.md rename to website/pages/docs/disks/hyperv/usage.mdx index 94046a50e..0aaf51d1a 100644 --- a/website/source/docs/disks/hyperv/usage.html.md +++ b/website/pages/docs/disks/hyperv/usage.mdx @@ -1,7 +1,7 @@ --- -layout: "docs" -page_title: "Usage - Disks Hyper-V Provider" -sidebar_current: "disks-providers-hyperv-usage" +layout: docs +page_title: Usage - Disks Hyper-V Provider +sidebar_title: Usage description: |- The Vagrant Hyper-V provider is used just like any other provider. Please read the general basic usage page for providers. @@ -9,24 +9,22 @@ description: |- # Usage -
- Warning! This feature is experimental and may break or - change in between releases. Use at your own risk. It currently is not officially - supported or functional. +~> **Warning!** This feature is experimental and may break or +change in between releases. Use at your own risk. It currently is not officially +supported or functional. - This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to: +This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to: - ``` - VAGRANT_EXPERIMENTAL="disks" - ``` +``` +VAGRANT_EXPERIMENTAL="disks" +``` - Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more - information about this flag visit the [Experimental docs page](/docs/experimental/) - for more info. Without this flag enabled, any disks defined will not be configured. -
+Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more +information about this flag visit the [Experimental docs page](/docs/experimental/) +for more info. Without this flag enabled, any disks defined will not be configured. For examples of how to use the disk feature with Hyper-V, please refer to the -[general disk usage guide](/docs/disks/usage.html) for more examples. +[general disk usage guide](/docs/disks/usage) for more examples. ## provider_config options @@ -35,7 +33,7 @@ Vagrant supports most options for these operations. You should be able to define the powershell specific argument to a given Hyper-V command in the provider_config hash, and Vagrant should properly pass it along to the command. -To define a provider specific option, please refer to the [Disk Options documentation page](/docs/disks/configuration.html) for more info. +To define a provider specific option, please refer to the [Disk Options documentation page](/docs/disks/configuration) for more info. ### Note about options defined below diff --git a/website/source/docs/disks/hyperv/index.html.md b/website/source/docs/disks/hyperv/index.html.md deleted file mode 100644 index b83640319..000000000 --- a/website/source/docs/disks/hyperv/index.html.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: "docs" -page_title: "Disks for Hyper-V Provider" -sidebar_current: "disks-providers-hyperv" -description: |- - Vagrant comes with support out of the box for Hyper-V, a free, - cross-platform consumer virtualization product. ---- - -# Hyper-V - -
- Warning! This feature is experimental and may break or - change in between releases. Use at your own risk. It currently is not officially - supported or functional. - - This feature currently reqiures the experimental flag to be used. To explicitly enable this feature, you can set the experimental flag to: - - ``` - VAGRANT_EXPERIMENTAL="disks" - ``` - - Please note that `VAGRANT_EXPERIMENTAL` is an environment variable. For more - information about this flag visit the [Experimental docs page](/docs/experimental/) - for more info. Without this flag enabled, any disks defined will not be configured. -
- -Because of how Hyper-V handles disk management, a Vagrant guest _must_ be powered -off for any changes to be applied to a guest. If you make a configuration change -with a guests disk, you will need to `vagrant reload` the guest for any changes -to be applied. - -For more information on how to use VirtualBox to configure disks for a guest, refer -to the [general usage](/docs/disks/usage.html) and [configuration](/docs/disks/configuration.html) -guide for more information.