<commit_before>require "log4r"
require "vagrant/util/numeric"
require "vagrant/util/experimental"

module VagrantPlugins
  module ProviderVirtualBox
    module Cap
      module ConfigureDisks
        LOGGER = Log4r::Logger.new("vagrant::plugins::virtualbox::configure_disks")

        # The max amount of disks that can be attached to a single device in a controller
        MAX_DISK_NUMER = 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?("virtualbox_disk_hdd")

          if defined_disks.size > MAX_DISK_NUMER
            # you can only attach up to 30 disks per controller, INCLUDING the primary disk
            raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit
          end

          machine.ui.info("Configuring storage mediums...")

          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.warn("Floppy disk configuration not yet supported. Skipping disk #{disk.name}...")
            elsif disk.type == :dvd
              # TODO: Write me
              machine.ui.warn("DVD disk configuration not yet supported. Skipping disk #{disk.name}...")
            end
          end

          return configured_disks
        end

        protected

        # Handles all disk configs of type `:disk`
        # @param [Hash] - disk_metadata
        def self.handle_configure_disk(machine, disk, all_disks)
          disk_metadata = {}

          # Grab the existing configured disk, if it exists
          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

          if !current_disk
            # create new disk and attach
            disk_metadata = create_disk(machine, disk)
          elsif compare_disk_state(machine, disk, current_disk)
            disk_metadata = resize_disk(machine, disk, current_disk)
          else
            LOGGER.info("No further configuration required for disk '#{disk.name}'")
            disk_metadata = {uuid: current_disk["UUID"], name: disk.name}
          end

          return 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_state(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("VirtualBox does not support shrinking disk size. Cannot shrink '#{disk_config.name}' disks size")
            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("Disk '#{disk_config.name}' not found in guest. Creating and attaching disk to guest...")
          guest_info = machine.provider.driver.show_vm_info
          disk_provider_config = disk_config.provider_config[:virtualbox] if disk_config.provider_config

          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_device(machine)
          machine.provider.driver.attach_disk(dsk_controller_info[:port], dsk_controller_info[:device], disk_file)

          disk_metadata
        end

        # Finds the next available port and or device for a given controller
        #
        # @param [Vagrant::Machine] machine
        # @return [Hash] dsk_info - The next available port and device on a given controller
        def self.get_next_port_device(machine)
          vm_info = machine.provider.driver.show_vm_info
          dsk_info = {device: "0", port: "0"}

          port = 0
          device = 0
          vm_info.each do |key,value|
            if key.include?("ImageUUID")
              disk_info = key.split("-")
              port = disk_info[2]
              device = disk_info[3]
            else
              next
            end<commit_msg>Rename method to match functionality<commit_after>require "log4r"
require "vagrant/util/numeric"
require "vagrant/util/experimental"

module VagrantPlugins
  module ProviderVirtualBox
    module Cap
      module ConfigureDisks
        LOGGER = Log4r::Logger.new("vagrant::plugins::virtualbox::configure_disks")

        # The max amount of disks that can be attached to a single device in a controller
        MAX_DISK_NUMER = 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?("virtualbox_disk_hdd")

          if defined_disks.size > MAX_DISK_NUMER
            # you can only attach up to 30 disks per controller, INCLUDING the primary disk
            raise Vagrant::Errors::VirtualBoxDisksDefinedExceedLimit
          end

          machine.ui.info("Configuring storage mediums...")

          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.warn("Floppy disk configuration not yet supported. Skipping disk #{disk.name}...")
            elsif disk.type == :dvd
              # TODO: Write me
              machine.ui.warn("DVD disk configuration not yet supported. Skipping disk #{disk.name}...")
            end
          end

          return configured_disks
        end

        protected

        # Handles all disk configs of type `:disk`
        # @param [Hash] - disk_metadata
        def self.handle_configure_disk(machine, disk, all_disks)
          disk_metadata = {}

          # Grab the existing configured disk, if it exists
          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

          if !current_disk
            # create new disk and attach
            disk_metadata = create_disk(machine, disk)
          elsif compare_disk_state(machine, disk, current_disk)
            disk_metadata = resize_disk(machine, disk, current_disk)
          else
            LOGGER.info("No further configuration required for disk '#{disk.name}'")
            disk_metadata = {uuid: current_disk["UUID"], name: disk.name}
          end

          return 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_state(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("VirtualBox does not support shrinking disk size. Cannot shrink '#{disk_config.name}' disks size")
            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("Disk '#{disk_config.name}' not found in guest. Creating and attaching disk to guest...")
          guest_info = machine.provider.driver.show_vm_info
          disk_provider_config = disk_config.provider_config[:virtualbox] if disk_config.provider_config

          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
        #
        # @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"}

          port = 0
          device = 0
          vm_info.each do |key,value|
            if key.include?("ImageUUID")
              disk_info = key.split("-")
              port = disk_info[2]
              device = disk_info[3]
            else
              next
            end
{'fraction_non_alphanumeric': 0.08546135512427647, 'fraction_numerical': 0.003234593122233572, 'mean_word_length': 2.296576879910213, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '930013', 'n_tokens_mistral': 3309, 'n_tokens_neox': 3236, 'n_words': 864}