module HashiCorp::VagrantVMwareDesktop::Cap::Disk

Constants

BUS_TYPES
DEFAULT_ADAPTER_TYPE
DEFAULT_BUS
DEFAULT_DISK_EXT
DEFAULT_DISK_TYPE

Disk types (from vmware-vdiskmanager -h) 0 : single growable virtual disk 1 : growable virtual disk split into multiple files 2 : preallocated virtual disk 3 : preallocated virtual disk split into multiple files 4 : preallocated ESX-type virtual disk 5 : compressed disk optimized for streaming 6 : thin provisioned virtual disk - ESX 3.x and above

DEFAULT_DVD_BUS
DEFAULT_DVD_DEVICE_TYPE
DISK_ADAPTER_TYPES

Adapter types (from vmware-vdiskmanager -h)

PRIMARY_DISK_SLOT

Public Class Methods

cleanup_disks(machine, defined_disks, disk_meta) click to toggle source

@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

@return [nil]

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 75
def self.cleanup_disks(machine, defined_disks, disk_meta)
  return if disk_meta.values.flatten.empty?

  ["disk", "dvd"].each do |k|
    if !disk_meta[k].is_a?(Array)
      raise TypeError, "Expected `Array` but received `#{disk_meta[k].class}`"
    end
  end

  # TODO: floppy
  disk_meta["disk"].each do |d|
    # If disk is defined or the primary disk, don't remove
    if d["primary"]
      @@logger.warn("Vagrant will not clean up the primary disk! Primary disk no longer tracked in Vagrantfile")
      next
    end
    next if defined_disks.any? { |dsk| dsk.name == d["Name"]}
    machine.provider.driver.remove_disk(File.basename(d["Path"]))
  end

  disk_meta["dvd"].each do |d|
    # If disk is defined, don't remove
    next if defined_disks.any? { |dsk| dsk.name == d["Name"]}
    machine.provider.driver.remove_disk_from_vmx(d["Path"], ["deviceType"])
  end
  nil
end
configure_disks(machine, defined_disks) click to toggle source

@param [Vagrant::Machine] machine @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] defined_disks @return [Hash] configured_disks - A hash of all the current configured disks

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 41
def self.configure_disks(machine, defined_disks)
  return {} if defined_disks.empty?

  attached_disks = machine.provider.driver.get_disks(BUS_TYPES)
  configured_disks = {disk: [], floppy: [], dvd: []}

  defined_disks.each do |disk|
    case disk.type
    when :disk
      disk_data = setup_disk(machine, disk, attached_disks)
      if !disk_data.empty?
        configured_disks[:disk] << disk_data
      end
    when :floppy
      # TODO: Write me
      machine.ui.info(I18n.t("hashicorp.vagrant_vmware_desktop.cap.disks.floppy_not_supported", name: disk.name))
    when :dvd
      disk_data = setup_dvd(machine, disk, attached_disks)
      if !disk_data.empty?
        configured_disks[:dvd] << disk_data
      end
    else
      @@logger.info("Invalid disk type #{disk.type}, carrying on.")
    end
  end

  configured_disks
end
default_disk_exts(machine) click to toggle source
# File lib/vagrant-vmware-desktop/cap/disk.rb, line 34
def self.default_disk_exts(machine)
  [DEFAULT_DISK_EXT].freeze
end
set_default_disk_ext(machine) click to toggle source
# File lib/vagrant-vmware-desktop/cap/disk.rb, line 30
def self.set_default_disk_ext(machine)
  DEFAULT_DISK_EXT
end

Protected Class Methods

create_disk(machine, disk_config, attached_disks) click to toggle source

Creates a disk and attaches disk by editing the machine’s vmx data

@param [Vagrant::Machine] machine @param [Kernel_V2::VagrantConfigDisk] disk_config @return [String] full path to disk file

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 199
def self.create_disk(machine, disk_config, attached_disks)
  if disk_config.file.nil? || !File.exist?(disk_config.file)
    # Create a new disk if a file is not provided, or that path does not exist
    disk_filename = "#{disk_config.name}.#{disk_config.disk_ext}"
    disk_provider_config = {}

    if disk_config.provider_config && disk_config.provider_config.key?(:vmware_desktop)
      disk_provider_config = disk_config.provider_config[:vmware_desktop]
      if !DISK_ADAPTER_TYPES.include?(disk_provider_config[:adapter_type])
        disk_provider_config[:adapter_type] = DEFAULT_ADAPTER_TYPE
        @@logger.warn("#{disk_provider_config[:adapter_type]} is not a valid. Should be one " \
          "of #{DISK_ADAPTER_TYPES.join(', ')}! Setting adapter type to #{DEFAULT_ADAPTER_TYPE}")
      end
      if !BUS_TYPES.include?(disk_provider_config[:bus_type])
        disk_provider_config[:bus_type] = DEFAULT_BUS
        @@logger.warn("#{disk_provider_config[:bus_type]} is not a valid. Should be one of " \
          "#{BUS_TYPES.join(', ')}! Setting adapter type to #{DEFAULT_BUS}")
      end
    end
    disk_type = DEFAULT_DISK_TYPE
    disk_adapter = disk_provider_config.fetch(:adapter_type, DEFAULT_ADAPTER_TYPE)
    bus = disk_provider_config.fetch(:bus_type,  DEFAULT_BUS)
    disk_path = machine.provider.driver.create_disk(disk_filename, disk_config.size, disk_type, disk_adapter)
  else
    # Don't create a new disk if one is provided by `file` config argument
    disk_path = disk_config.file
  end

  slot = get_slot(bus, attached_disks)
  machine.provider.driver.add_disk_to_vmx(File.basename(disk_path), slot)
  # Add newly attached disk
  attached_disks[slot] = { "filename" => disk_filename }
  disk_path
end
get_disk(disk, all_disks) click to toggle source

Retrieves a disk from a Hash of all the disks

@param [Config::Disk] disk - the current disk to configure @param [Hash] all_disks - A hash of all currently defined disks @return [Hash, nil] - A hash of the current disk, nil if not found

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 110
def self.get_disk(disk, all_disks)
  if disk.primary
    return all_disks[PRIMARY_DISK_SLOT]
  else
    if disk.type == :dvd
      all_disks.values.detect { |v| v["filename"] == disk.file }
    else
      all_disks.values.detect do |v|
        m_ext = File.extname(v["filename"])
        m_fil = v["filename"].sub(/#{Regexp.escape(m_ext)}$/, "")
        m_ext.sub!(".", "")
        m_ext == disk.disk_ext &&
          (m_fil == disk.name || m_fil =~ /^#{Regexp.escape(disk.name)}-\d+$/)
      end
    end
  end
end
get_slot(bus, attached_disks) click to toggle source

Gets the next slot available

@param [String] bus name, one of BUS_TYPES @param [Hash] attached disks

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 253
def self.get_slot(bus, attached_disks)
  bus_num = 0
  slot_num = 0
  attached_disks.keys.each do |k|
   s = k.match(/(?<=#{bus})(\d+:\d+)/)
   if !s.nil?
    bus_and_slot = s[0].split(":")
    if bus_and_slot[0].to_i > bus_num
      bus_num = bus_and_slot[0].to_i
      # reset slot num
      slot_num = 0
    end
    if bus_and_slot[1].to_i > slot_num
      slot_num = bus_and_slot[1].to_i
    end
   end
  end

  # For ide bus the slot number must be 0 or 1
  if bus.to_s == "ide"
    bus_num = bus_num + (slot_num%2)
    slot_num = (slot_num+1)%2
    if bus_num > 1
      @@logger.warn("attaching disk to #{bus}#{bus_num}:#{slot_num}, this will " \
        "likely cause the disk to be unavailable, consider attaching the disk to a different bus")
    end
  else
    slot_num = slot_num + 1
  end
  "#{bus}#{bus_num}:#{slot_num}"
end
grow_disk(machine, disk_path, disk_config) click to toggle source

Expand an existing disk

@param [Vagrant::Machine] machine @param [String] disk_path Path to disk for expansion @param [VagrantPlugins::Kernel_V2::VagrantConfigDisk] disk_config @return [nil]

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 240
def self.grow_disk(machine, disk_path, disk_config)
  if machine.provider.driver.snapshot_list.empty?
    machine.provider.driver.grow_disk(disk_path, disk_config.size)
  else
    raise Errors::DiskNotResizedSnapshot, path: disk_path
  end
  nil
end
setup_disk(machine, disk, attached_disks) click to toggle source

Sets up 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

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 134
def self.setup_disk(machine, disk, attached_disks)
  current_disk = get_disk(disk, attached_disks)

  if current_disk.nil?
    disk_path = create_disk(machine, disk, attached_disks)
  else
    # If the path matches the disk name + some extra characters then
    # make sure to remove the extra characters. They may take the form
    # <name>-f.vmdk, <name>-f<num>.vmdk, <name>-s<num>.vmdk, <name>-s.vmdk, <name>-flat.vmdk, <name>-delta.vmdk
    # ref: https://github.com/libyal/libvmdk/blob/master/documentation/VMWare%20Virtual%20Disk%20Format%20(VMDK).asciidoc
    if current_disk["filename"].match(/\w+-(f\d*|s\d*|flat|delta).vmdk/)
      file_name = current_disk["filename"].gsub(/-(f\d*|s\d*|flat|delta)/, "")
      disk_path = File.join(File.dirname(machine.provider.driver.vmx_path), file_name)
    else
      disk_path = File.join(File.dirname(machine.provider.driver.vmx_path), current_disk["filename"])
    end

    # disk.size is in bytes
    if disk.size > machine.provider.driver.get_disk_size(disk_path)
      grow_disk(machine, disk_path, disk)
    elsif disk.size < machine.provider.driver.get_disk_size(disk_path)
      machine.env.ui.warn(I18n.t("hashicorp.vagrant_vmware_desktop.disk_not_shrinking", path: disk.name))
      @@logger.warn("Not shrinking disk #{disk.name}")
    else
      @@logger.info("Not changing #{disk.name}")
    end
  end
  {UUID: disk.id, Name: disk.name, Path: disk_path, primary: !!disk.primary}
end
setup_dvd(machine, disk, attached_disks) click to toggle source

Sets up all disk configs of type ‘:dvd`

@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

# File lib/vagrant-vmware-desktop/cap/disk.rb, line 170
def self.setup_dvd(machine, disk, attached_disks)
  disk_provider_config = {}
  if disk.provider_config && disk.provider_config.key?(:vmware_desktop)
    disk_provider_config = disk.provider_config[:vmware_desktop]
    if !BUS_TYPES.include?(disk_provider_config[:bus_type])
      disk_provider_config[:bus_type] = DEFAULT_DVD_BUS
      @@logger.warn("#{disk_provider_config[:bus_type]} is not a valid. Should be one of " \
        "#{BUS_TYPES.join(', ')}! Setting adapter type to #{DEFAULT_DVD_BUS}")
    end
  end

  current_disk = get_disk(disk, attached_disks)
  bus = disk_provider_config.fetch(:bus_type, DEFAULT_DVD_BUS)
  if current_disk.nil?
    # Attach dvd if not already attached
    slot = get_slot(bus, attached_disks)
    dvd_opts = {"deviceType" => disk_provider_config.fetch(:device_type, DEFAULT_DVD_DEVICE_TYPE)}
    machine.provider.driver.add_disk_to_vmx(disk.file, slot, dvd_opts)
    # Add newly attached disk
    attached_disks[slot] = {"filename" => disk.file}
  end
  {UUID: disk.id, Name: disk.name, Path: disk.file, primary: !!disk.primary}
end