Class: VirtualBox::HardDrive

Inherits:
Medium show all
Includes:
ByteNormalizer
Defined in:
lib/virtualbox/hard_drive.rb

Overview

Represents a hard disk which is registered with VirtualBox.

# Finding a Hard Drive

Hard drives can be found use HardDrive.all and HardDrive.find, which find all or a specific hard drive, respectively. Example below:

VirtualBox::HardDrive.all

Or use find with the UUID of the HardDrive:

VirtualBox::HardDrive.find("4a896f0b-b3a3-4dec-8c26-8406c6fccd6e")

# Creating a Hard Drive

Hard Drives can be created by intilizing an empty hard drive, assigning values to the necessary attributes, and calling save on the object. Below is a simple example of how this works:

hd = VirtualBox::HardDrive.new
hd.format = "VDI" # Or any format list with `VBoxManage list hddbackends`
hd.location = "foo.vdi"
hd.size = 2400 # in megabytes
hd.save

# You can now access other attributes, since its saved:
hd.uuid
hd.location # will return a full path now

# Destroying Hard Drives

Hard drives can also be deleted. **This operation is not reversable**.

hd = VirtualBox::HardDrive.find("...")
hd.destroy

This will only unregister the Hard Drive from VirtualBox and will not destroy the storage space on the disk. To destroy the storage space, pass ‘true` to the destroy method, example:

hd.destroy(true)

# Cloning Hard Drives

Hard Drives can just as easily be cloned as they can be created or destroyed.

hd = VirtualBox::HardDrive.find("...")
cloned_hd = hd.clone("bar.vdi")

In addition to simply cloning hard drives, this command can be used to clone to a different format. If the format is not passed in (as with the the above example, the system default format will be used). example:

hd = VirtualBox::HardDrive.find("...")
hd.clone("bar.vmdk", "VMDK") # Will clone and convert to VMDK format

# Attributes

Properties of the model are exposed using standard ruby instance methods which are generated on the fly. Because of this, they are not listed below as available instance methods.

These attributes can be accessed and modified via standard ruby-style ‘instance.attribute` and `instance.attribute=` methods. The attributes are listed below. If you aren’t sure what this means or you can’t understand why the below is listed, please read AbstractModel::Attributable.

attribute :format, :default => "VDI"
attribute :location
attribute :logical_size
attribute :physical_size, :readonly => true, :property => :size

There are more attributes on the Medium model, which HardDrive inherits from.

Constant Summary

Constants included from ByteNormalizer

ByteNormalizer::BYTE, ByteNormalizer::KILOBYTE, ByteNormalizer::MEGABYTE, ByteNormalizer::THOUSAND

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ByteNormalizer

#bytes_to_megabytes, #megabytes_to_bytes

Methods inherited from Medium

#destroy, #destroy_storage, #filename, #initialize_attributes, #load_relationship, populate_array_relationship, populate_relationship, populate_single_relationship

Methods included from SubclassListing

included

Methods inherited from AbstractModel

#destroy, #errors, errors_for_relationship, #existing_record!, #inspect, #lazy_attribute?, #lazy_relationship?, #new_record!, #new_record?, #parent_machine, #populate_attributes, #populate_relationship, #populate_relationships, reload!, #reload!, reload?, reloaded!, #save!, #save_attribute, #save_changed_interface_attributes, #save_interface_attribute, #set_relationship, #write_attribute

Methods included from AbstractModel::Validatable

#__validates_extract_options, #add_error, #clear_errors, #errors, #errors_on, #full_error_messages, #valid?, #validates_format_of, #validates_inclusion_of, #validates_numericality_of, #validates_presence_of

Methods included from AbstractModel::Relatable

#destroy_relationship, #destroy_relationships, #has_relationship?, included, #lazy_relationship?, #loaded_relationship?, #populate_relationship, #populate_relationships, #read_relationship, #relationship_class, #relationship_data, #save_relationship, #save_relationships, #set_relationship

Methods included from AbstractModel::VersionMatcher

#assert_version_match, #split_version, #version_match?

Methods included from AbstractModel::Dirty

#changed?, #changes, #clear_dirty!, #ignore_dirty, #method_missing, #set_dirty!

Methods included from AbstractModel::InterfaceAttributes

#load_interface_attribute, #load_interface_attributes, #save_interface_attribute, #save_interface_attributes, #spec_to_proc

Methods included from AbstractModel::Attributable

#attributes, #has_attribute?, included, #lazy_attribute?, #loaded_attribute?, #populate_attributes, #read_attribute, #readonly_attribute?, #write_attribute

Methods included from Logger

included, #logger, #logger_output=

Constructor Details

#initialize(imedium = nil) ⇒ HardDrive

Overwrite the AbstractModel initialize to make the imedium parameter optional so that new Hard Drives can be created



111
112
113
# File 'lib/virtualbox/hard_drive.rb', line 111

def initialize(imedium = nil)
  super if imedium
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class VirtualBox::AbstractModel::Dirty

Class Method Details

.allArray<HardDrive>

Returns an array of all available hard drives as HardDrive objects.

Returns:



90
91
92
# File 'lib/virtualbox/hard_drive.rb', line 90

def all
  Global.global(true).media.hard_drives
end

.device_typeObject

Override of Medium.device_type.



104
105
106
# File 'lib/virtualbox/hard_drive.rb', line 104

def device_type
  :hard_disk
end

.find(id) ⇒ HardDrive

Finds one specific hard drive by UUID. If the hard drive can not be found, will return ‘nil`.

Parameters:

  • id (String)

    The UUID of the hard drive

Returns:



99
100
101
# File 'lib/virtualbox/hard_drive.rb', line 99

def find(id)
  all.detect { |hd| hd.uuid == id }
end

Instance Method Details

#clone(outputfile, format = nil) ⇒ HardDrive

Clone hard drive, possibly also converting formats. All formats supported by your local VirtualBox installation are supported here. If no format is specified, the systems default will be used.

Parameters:

  • outputfile (String)

    The output file. This can be a full path or just a filename. If its just a filename, it will be placed in the default hard drives directory. Should not be present already.

  • format (String) (defaults to: nil)

    The format to convert to. If not present, the systems default will be used.

Returns:

  • (HardDrive)

    The new, cloned hard drive, or nil on failure.



188
189
190
191
192
193
194
195
196
197
# File 'lib/virtualbox/hard_drive.rb', line 188

def clone(outputfile, format = nil)
  # Create the new Hard Disk medium
  new_medium = create_hard_disk_medium(outputfile, format)

  # Clone the current drive onto the new Hard Disk medium
  interface.clone_to(new_medium, :standard, nil).wait_for_completion(-1)

  # Locate the newly cloned hard drive
  self.class.find(new_medium.id) if new_medium.respond_to?(:id)
end

#createBoolean

Creates a new hard drive.

**This method should NEVER be called. Call #save instead.**

Returns:

  • (Boolean)

    True if command was successful, false otherwise.

Raises:



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/virtualbox/hard_drive.rb', line 204

def create
  return false unless new_record?
  raise Exceptions::ValidationFailedException.new(errors) if !valid?

  # Create the new Hard Disk medium
  new_medium = create_hard_disk_medium(location, format)

  # Create the storage on the host system
  new_medium.create_base_storage(logical_size, :standard).wait_for_completion(-1)

  # Update the current Hard Drive instance with the uuid and
  # other attributes assigned after storage was written
  write_attribute(:interface, new_medium)
  initialize_attributes(new_medium)

  # If the uuid is present, then everything worked
  uuid && !uuid.to_s.empty?
end

#create_hard_disk_medium(outputfile, format = nil) ⇒ COM::Interface::Medium

Creates a new COM::Interface::Medium instance. This simply creates the new COM::Interface::Medium structure. It does not (and shouldn’t) create the storage space on the host system. See the create method for an example on to create the storage space.

Parameters:

  • outputfile (String)

    The output file. This can be a full path or just a filename. If its just a filename, it will be placed in the default hard drives directory. Should not be present already.

  • format (String) (defaults to: nil)

    The format to convert to. If not present, the systems default will be used.

Returns:

Raises:



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/virtualbox/hard_drive.rb', line 151

def create_hard_disk_medium(outputfile, format = nil)
  # Get main VirtualBox object
  virtualbox = Lib.lib.virtualbox

  # Assign the default format if it isn't set yet
  format ||= virtualbox.system_properties.default_hard_disk_format

  # Expand path relative to the default hard disk folder. This allows
  # filenames to exist in the default folder while full paths will use
  # the paths specified.
  outputfile = File.expand_path(outputfile, virtualbox.system_properties.default_hard_disk_folder)

  # If the outputfile path is in use by another Hard Drive, lets fail
  # now with a meaningful exception rather than simply return a nil
  raise Exceptions::MediumLocationInUseException.new(outputfile) if File.exist?(outputfile)

  # Create the new {COM::Interface::Medium} instance.
  new_medium = virtualbox.create_hard_disk(format, outputfile)

  # Raise an error if the creation of the {COM::Interface::Medium}
  # instance failed
  raise Exceptions::MediumCreationFailedException.new unless new_medium

  # Return the new {COM::Interface::Medium} instance.
  new_medium
end

#machinesObject

Get an array of machines attached to this Virtual Machine



121
122
123
# File 'lib/virtualbox/hard_drive.rb', line 121

def machines
  interface.machine_ids.collect { |id| VirtualBox::VM.find(id) }
end

#physical_sizeObject

Custom getter to convert the physical size from bytes to megabytes.



116
117
118
# File 'lib/virtualbox/hard_drive.rb', line 116

def physical_size
  bytes_to_megabytes(read_attribute(:physical_size))
end

#saveBoolean

Saves the hard drive object. If the hard drive is new, this will create a new hard drive. Otherwise, it will save any other details about the existing hard drive.

Currently, **saving existing hard drives does nothing**. This is a limitation of VirtualBox, rather than the library itself.

Returns:

  • (Boolean)

    True if command was successful, false otherwise.

Raises:



231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/virtualbox/hard_drive.rb', line 231

def save
  return true if !new_record? && !changed?
  raise Exceptions::ValidationFailedException.new(errors) if !valid?

  if new_record?
    create # Create a new hard drive
  else
    # Mediums like Hard Drives are not updatable, they need to be recreated
    # Because Hard Drives contain info and paritions, it's easier to error
    # out now than try and do some complicated logic
    msg = "Hard Drives cannot be updated. You need to create one from scratch."
    raise Exceptions::MediumNotUpdatableException.new(msg)
  end
end

#validateObject

Validates a hard drive for the minimum attributes required to create or save.



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/virtualbox/hard_drive.rb', line 127

def validate
  super

  medium_formats = Global.global.system_properties.medium_formats.collect { |mf| mf.id }
  validates_inclusion_of :format, :in => medium_formats, :message => "must be one of the following: #{medium_formats.join(', ')}."

  validates_presence_of :location

  max_vdi_size = Global.global.system_properties.max_vdi_size
  validates_inclusion_of :logical_size, :in => (0..max_vdi_size), :message => "must be between 0 and #{max_vdi_size}."
end