lib/virtualbox/vm.rb in virtualbox-0.4.3 vs lib/virtualbox/vm.rb in virtualbox-0.5.0

- old
+ new

@@ -40,10 +40,11 @@ # attributes. If you don't understand what this means, read {Attributable}. # # attribute :uuid, :readonly => true # attribute :name # attribute :ostype + # attribute :description, :readonly => true # attribute :memory # attribute :vram # attribute :acpi # attribute :ioapic # attribute :cpus @@ -61,37 +62,44 @@ # attribute :boot3 # attribute :boot4 # attribute :clipboard # attribute :monitorcount # attribute :usb + # attribute :ehci # attribute :audio + # attribute :audiocontroller + # attribute :audiodriver # attribute :vrdp - # attribute :vrdpports + # attribute :vrdpport + # attribute :vrdpauthtype + # attribute :vrdpauthtimeout # attribute :state, :populate_key => :vmstate, :readonly => true # # ## Relationships # # In addition to the basic attributes, a virtual machine is related # to other things. The relationships are listed below. If you don't # understand this, read {Relatable}. # # relationship :nics, Nic + # relationship :usbs, USB # relationship :storage_controllers, StorageController, :dependent => :destroy # relationship :shared_folders, SharedFolder # relationship :extra_data, ExtraData # relationship :forwarded_ports, ForwardedPort # class VM < AbstractModel attribute :uuid, :readonly => true attribute :name attribute :ostype + attribute :description, :readonly => true attribute :memory attribute :vram attribute :acpi attribute :ioapic attribute :cpus - attribute :synthcpu + attribute :synthcpu, :lazy => true attribute :pae attribute :hwvirtex attribute :hwvirtexexcl attribute :nestedpaging attribute :vtxvpid @@ -103,39 +111,55 @@ attribute :boot3 attribute :boot4 attribute :clipboard attribute :monitorcount attribute :usb + attribute :ehci attribute :audio + attribute :audiocontroller + attribute :audiodriver attribute :vrdp - attribute :vrdpports - attribute :state, :populate_key => :vmstate, :readonly => true + attribute :vrdpport + attribute :vrdpauthtype + attribute :vrdpauthtimeout + attribute :state, :populate_key => :vmstate, :readonly => true, :lazy => true relationship :nics, Nic + relationship :usbs, USB relationship :storage_controllers, StorageController, :dependent => :destroy relationship :shared_folders, SharedFolder relationship :extra_data, ExtraData relationship :forwarded_ports, ForwardedPort class <<self # Returns an array of all available VMs. # # @return [Array<VM>] - def all - raw = Command.vboxmanage("list", "vms") - parse_vm_list(raw) + def all(reload=false) + Global.global(reload).vms end # Finds a VM by UUID or registered name and returns a # new VM object. If the VM doesn't exist, will return `nil`. # # @return [VM] def find(name) - new(raw_info(name)) - rescue Exceptions::CommandFailedException - nil + all(true).detect { |o| o.name == name || o.uuid == name } end + # Loads a VM from its XML configuration file. All VMs managed + # by VirtualBox have an XML configuration file somewhere. If + # given the path, this will instantiate the VM that way. Typically + # this method will only be called internally. Users of the class + # should use {all} or {find} instead. + # + # @param [String] location Full path to the XML file. + # @return [VM] + def load_from_xml(location) + vm_doc = Command.parse_xml(location) + new(vm_doc) + end + # Imports a VM, blocking the entire thread during this time. # When finished, on success, will return the VM object. This # VM object can be used to make any modifications necessary # (RAM, cpus, etc.). # @@ -145,20 +169,10 @@ return nil unless raw find(parse_vm_name(raw)) end - # Gets the non-machine-readable info for a given VM and returns - # it as a raw string. - # - # **This method typically won't be used except internally.** - # - # @return [String] - def human_info(name) - Command.vboxmanage("showvminfo", name) - end - # Gets the VM info (machine readable) for a given VM and returns it # as a hash. # # @return [Hash] Parsed VM info. def raw_info(name) @@ -202,10 +216,21 @@ # @return [String] Parsed VM name def parse_vm_name(raw) return nil unless raw =~ /VM name "(.+?)"/ $1.to_s end + + def populate_relationship(caller, doc) + result = Proxies::Collection.new(caller) + + doc.css("Global MachineRegistry MachineEntry").each do |entry| + location = Global.expand_path(entry[:src]) + result << load_from_xml(location) + end + + result + end end # Creates a new instance of a virtual machine. # # **Currently can NOT be used to create a NEW virtual machine**. @@ -213,25 +238,93 @@ # For now, this is only used by {VM.find} and {VM.all} to # initialize the VMs. def initialize(data) super() - populate_attributes(data) - @original_name = data[:name] + initialize_attributes(data) + populate_relationships(data) + @original_name = name end + def initialize_attributes(doc) + attribute_associations = { + :uuid => ["Machine", :uuid], + :name => ["Machine", :name], + :ostype => ["Machine", :OSType], + :description => ["Machine Description"], + :memory => ["Hardware Memory", :RAMSize], + :vram => ["Hardware Display", :VRAMSize], + :acpi => ["Hardware BIOS ACPI", :enabled], + :ioapic => ["Hardware BIOS IOAPIC", :enabled], + :cpus => ["Hardware CPU", :count], + :pae => ["Hardware CPU PAE", :enabled], + :hwvirtex => ["Hardware CPU HardwareVirtEx", :enabled], + :hwvirtexexcl => ["Hardware CPU HardwareVirtEx", :exclusive], + :nestedpaging => ["Hardware CPU HardwareVirtExNestedPaging", :enabled], + :vtxvpid => ["Hardware CPU HardwareVirtExVPID", :enabled], + :accelerate3d => ["Hardware Display", :accelerate3D], + :accelerate2dvideo => ["Hardware Display", :accelerate2DVideo], + :biosbootmenu => ["Hardware BIOS BootMenu", :mode], + :boot1 => ["Hardware Boot Order[position=\"1\"]", :device], + :boot2 => ["Hardware Boot Order[position=\"2\"]", :device], + :boot3 => ["Hardware Boot Order[position=\"3\"]", :device], + :boot4 => ["Hardware Boot Order[position=\"4\"]", :device], + :clipboard => ["Hardware Clipboard", :mode], + :monitorcount => ["Hardware Display", :monitorCount], + :usb => ["Hardware USBController", :enabled], + :ehci => ["Hardware USBController", :enabledEhci], + :audio => ["Hardware AudioAdapter", :enabled], + :audiocontroller => ["Hardware AudioAdapter", :controller], + :audiodriver => ["Hardware AudioAdapter", :driver], + :vrdp => ["Hardware RemoteDisplay", :enabled], + :vrdpport => ["Hardware RemoteDisplay", :port], + :vrdpauthtype => ["Hardware RemoteDisplay", :authType], + :vrdpauthtimeout => ["Hardware RemoteDisplay", :authTimeout], + } + + attribute_associations.each do |name, search_data| + css, key = search_data + node = doc.css(css)[0] + + # key is passed in for attributes, else you get the element inner text + value = (key ? node[key] : node.inner_text) if node + + # Special cases + value = value[1..-2] if name == :uuid + + write_attribute(name, value) + end + + # 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_attribute(name) + info = self.class.raw_info(@original_name) + + if name == :state + # Simply force a state reload, and it'll write the attribute up + write_attribute(:state, info[:vmstate]) + end + + write_attribute(:synthcpu, info[:synthcpu]) unless loaded_attribute?(:synthcpu) + end + # State of the virtual machine. Returns the state of the virtual # machine. This state will represent the state that was assigned # when the VM was found unless `reload` is set to `true`. # # @param [Boolean] reload If true, will reload the state to current # value. # @return [String] Virtual machine state. def state(reload=false) if reload - info = self.class.raw_info(@original_name) - write_attribute(:state, info[:vmstate]) + load_attribute(:state) end read_attribute(:state) end @@ -246,10 +339,13 @@ @original_name = name end super() + # Force reload + Global.reload! + true rescue Exceptions::CommandFailedException raise if raise_errors return false end @@ -418,10 +514,15 @@ def destroy(*args) # Call super first to destroy relationships, necessary before # unregistering a VM super - Command.vboxmanage("unregistervm", @original_name, "--delete") + if Command.vboxmanage("unregistervm", @original_name, "--delete") + Global.reload! + return true + else + return false + end end # Returns true if the virtual machine state is running # # @return [Boolean] True if virtual machine state is running \ No newline at end of file