require 'virtualbox/ext/subclass_listing' module VirtualBox # Represents a medium object part of VirtualBox. A medium is a # hard drive, DVD, floppy disk, etc. Each of these share common # properties represented here. class Medium < AbstractModel include SubclassListing attribute :uuid, :readonly => true, :property => :id attribute :type, :readonly => true attribute :description, :readonly => true attribute :location, :readonly => true attribute :state, :readonly => true, :property => :refresh_state attribute :interface, :readonly => true, :property => false relationship :children, :Medium, :lazy => true class << self # Populates a relationship with another model. Depending on the data sent # through as the `media` parameter, this can either return a single value # or an array of values. {Global}, for example, has a relationship of media, # while a {MediumAttachment} has a relationship with a single medium. # # **This method typically won't be used except internally.** def populate_relationship(caller, media) if media.is_a?(Array) # has many relationship populate_array_relationship(caller, media) else # has one relationship populate_single_relationship(caller, media) end end # Populates a relationship which has many media. # # **This method typically won't be used except internally.** # # @return [Array] def populate_array_relationship(caller, media) relation = Proxies::Collection.new(caller) media.each do |medium| # Skip media this class isn't interested in next if device_type != :all && medium.device_type != device_type # Wrap it up and add to the relationship relation << new(medium) end relation end # Populates a relationship which has one medium. This method goes one step # further and instantiates the proper class for the type of medium given. # For example, given a `device_type` of `:hard_drive`, it would return a # {HardDrive} object. # # **This method typically won't be used except internally.** # # @return [Medium] def populate_single_relationship(caller, medium) return nil if medium.nil? subclasses.each do |subclass| # Skip this class unless the device type matches next unless subclass.device_type == medium.device_type # Wrap it up and return it return subclass.new(medium) end # If all else fails, just wrap it in a Medium new(medium) end # Specifies the device type that a {Medium} class is interested in. This # is `:all` on {Medium}, but is expected to be overridden by child classes. # The value returned should be one of {COM::Interface::DeviceType}. # # @return [Symbol] def device_type :all end end # Initializes a medium object, retrieving the attributes and information # from the {COM::Interface::Medium} object given as the parameter. This initialization # is done automatically by virtualbox when populating a relationship. Mediums should # never be initialized manually. # # @param [COM::Interface::Medium] imedium def initialize(imedium) write_attribute(:interface, imedium) initialize_attributes(imedium) end def initialize_attributes(imedium) # First refresh the state (required for many attributes) imedium.refresh_state # Load interface attributes load_interface_attributes(imedium) # Clear dirtiness, since this should only be called initially and # therefore shouldn't affect dirtiness clear_dirty! # But this is an existing record existing_record! end def load_relationship(name) # Populate children populate_relationship(name, interface.children) end # Returns the basename of the images location (the file name +extension) # # @return [String] def filename File.basename(location.to_s) end # Destroys the medium, optionally also phsyically destroying the backing # storage. This removes this medium from the VirtualBox media registry. # In order to remove the medium, it must not be attached to any virtual # machine. If it is, an exception of some sort will be raised. # This action happens *immediately* when the method is called, and is not # deferred to a save. def destroy(destroy_backing=false) if destroy_backing destroy_storage else interface.close end end # Destroys the backing store of the medium and the media registry. This is # analagous to calling {#destroy} with the first parameter set to true. This # method requires that the medium not be attached to any virtual machine # (running or not). def destroy_storage interface.delete_storage.wait_for_completion(-1) end end end