lib/virtualbox/vm.rb in virtualbox-0.4.1 vs lib/virtualbox/vm.rb in virtualbox-0.4.2

- old
+ new

@@ -1,8 +1,8 @@ module VirtualBox # Represents a single VirtualBox virtual machine. All attributes which are - # not read-only can be modified and saved. + # not read-only can be modified and saved. # # # Finding Virtual Machines # # Two methods are used to find virtual machines: {VM.all} and {VM.find}. Each # return a {VM} object. An example is shown below: @@ -19,23 +19,23 @@ # vm.memory = 256 # vm.name = "WindowsXP" # vm.save # # # Attributes and Relationships - # + # # Properties of the virtual machine 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. + # 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. # # Relationships are also accessed like attributes but can't be set. Instead, # they are typically references to other objects such as a {HardDrive} which # in turn have their own attributes which can be modified. - # + # # ## Attributes # # This is copied directly from the class header, but lists all available # attributes. If you don't understand what this means, read {Attributable}. # @@ -52,20 +52,22 @@ # attribute :hwvirtex # attribute :hwvirtexexcl # attribute :nestedpaging # attribute :vtxvpid # attribute :accelerate3d + # attribute :accelerate2dvideo # attribute :biosbootmenu, :populate_key => :bootmenu # attribute :boot1 # attribute :boot2 # attribute :boot3 # attribute :boot4 # attribute :clipboard # attribute :monitorcount # attribute :usb # attribute :audio # attribute :vrdp + # attribute :vrdpports # attribute :state, :populate_key => :vmstate, :readonly => true # # ## Relationships # # In addition to the basic attributes, a virtual machine is related @@ -92,76 +94,80 @@ attribute :hwvirtex attribute :hwvirtexexcl attribute :nestedpaging attribute :vtxvpid attribute :accelerate3d + attribute :accelerate2dvideo attribute :biosbootmenu, :populate_key => :bootmenu attribute :boot1 attribute :boot2 attribute :boot3 attribute :boot4 attribute :clipboard attribute :monitorcount attribute :usb attribute :audio attribute :vrdp + attribute :vrdpports attribute :state, :populate_key => :vmstate, :readonly => true relationship :nics, Nic 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) 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 end - - # Imports a VM, blocking the entire thread during this time. + + # 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.). # # @return [VM] The newly imported virtual machine def import(source_path) raw = Command.vboxmanage("import #{Command.shell_escape(source_path)}") 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 #{Command.shell_escape(name)}") end - + # Gets the VM info (machine readable) for a given VM and returns it - # as a hash. + # as a hash. # # @return [Hash] Parsed VM info. def raw_info(name) raw = Command.vboxmanage("showvminfo #{Command.shell_escape(name)} --machinereadable") parse_vm_info(raw) end - + # Parses the machine-readable format outputted by VBoxManage showvminfo # into a hash. Ignores lines which don't match the format. def parse_vm_info(raw) parsed = {} raw.split("\n").each do |line| @@ -170,11 +176,11 @@ parsed[$1.downcase.to_sym] = $2.strip end parsed end - + # Parses the list of VMs returned by the "list vms" command used # in {VM.all}. # # **This method typically won't be used except internally.** # @@ -183,38 +189,38 @@ results = [] raw.split("\n").each do |line| next unless line =~ /^"(.+?)"\s+\{(.+?)\}$/ results.push(find($1.to_s)) end - + results end - + # Parses the vm name from the import results. # # **This method typically won't be used except internally.** # # @return [String] Parsed VM name def parse_vm_name(raw) return nil unless raw =~ /VM name "(.+?)"/ $1.to_s end end - + # Creates a new instance of a virtual machine. # # **Currently can NOT be used to create a NEW virtual machine**. # Support for creating new virtual machines will be added shortly. # 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] 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 @@ -223,42 +229,42 @@ def state(reload=false) if reload info = self.class.raw_info(@original_name) write_attribute(:state, info[:vmstate]) end - + read_attribute(:state) end - + # Saves the virtual machine if modified. This method saves any modified # attributes of the virtual machine. If any related attributes were saved # as well (such as storage controllers), those will be saved, too. def save(raise_errors=false) # Make sure we save the new name first if that was changed, or # we'll get some inconsistencies later if name_changed? save_attribute(:name, name) @original_name = name end - + super() - + true rescue Exceptions::CommandFailedException raise if raise_errors return false end - + # Saves a single attribute of the virtual machine. This should **not** # be called except interally. Instead, you're probably looking for {#save}. # # **This method typically won't be used except internally.** def save_attribute(key, value) - Command.vboxmanage("modifyvm #{@original_name} --#{key} #{Command.shell_escape(value.to_s)}") + Command.vboxmanage("modifyvm #{Command.shell_escape(@original_name)} --#{key} #{Command.shell_escape(value.to_s)}") super end - + # Exports a virtual machine. The virtual machine will be exported # to the specified OVF file name. This directory will also have the # `mf` file which contains the file checksums and also the virtual # drives of the machine. # @@ -281,99 +287,111 @@ # @option options [String] :eulafile (nil) License file def export(filename, options={}, raise_error=false) options = options.inject([]) do |acc, kv| acc.push("--#{kv[0]} #{Command.shell_escape(kv[1])}") end - + options.unshift("--vsys 0") unless options.empty? - - raw = Command.vboxmanage("export #{@original_name} -o #{Command.shell_escape(filename)} #{options.join(" ")}".strip) + + raw = Command.vboxmanage("export #{Command.shell_escape(@original_name)} -o #{Command.shell_escape(filename)} #{options.join(" ")}".strip) true rescue Exceptions::CommandFailedException raise if raise_error false end - + # Starts the virtual machine. The virtual machine can be started in a # variety of modes: # # * **gui** -- The VirtualBox GUI will open with the screen of the VM. - # * **headless** -- The VM will run in the background. No GUI will be + # * **headless** -- The VM will run in the background. No GUI will be # present at all. # # All modes will start their processes and return almost immediately. # Both the GUI and headless mode will not block the ruby process. # # @param [Symbol] mode Described above. # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} # will be raised if the command failed. # @return [Boolean] True if command was successful, false otherwise. def start(mode=:gui, raise_errors=false) - Command.vboxmanage("startvm #{@original_name} --type #{mode}") + Command.vboxmanage("startvm #{Command.shell_escape(@original_name)} --type #{mode}") true rescue Exceptions::CommandFailedException raise if raise_errors false end - + + # Shuts down the VM by directly calling "acpipowerbutton". Depending on the + # settings of the Virtual Machine, this may not work. For example, some linux + # installations don't respond to the ACPI power button at all. In such cases, + # {#stop} or {#save_state} may be used instead. + # + # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} + # will be raised if the command failed. + # @return [Boolean] True if command was successful, false otherwise. + def shutdown(raise_errors=false) + control(:acpipowerbutton, raise_errors) + end + # Stops the VM by directly calling "poweroff." Immediately halts the # virtual machine without saving state. This could result in a loss - # of data. + # of data. To prevent data loss, see {#shutdown} # # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} # will be raised if the command failed. # @return [Boolean] True if command was successful, false otherwise. def stop(raise_errors=false) control(:poweroff, raise_errors) end - + # Pauses the VM, putting it on hold temporarily. The VM can be resumed # again by calling {#resume} # # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} # will be raised if the command failed. # @return [Boolean] True if command was successful, false otherwise. def pause(raise_errors=false) control(:pause, raise_errors) end - + # Resume a paused VM. # # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} # will be raised if the command failed. # @return [Boolean] True if command was successful, false otherwise. def resume(raise_errors=false) control(:resume, raise_errors) end - + # Saves the state of a VM and stops it. The VM can be resumed # again by calling "start" again. # # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} # will be raised if the command failed. # @return [Boolean] True if command was successful, false otherwise. def save_state(raise_errors=false) control(:savestate, raise_errors) end - + # Controls the virtual machine. This method is used by {#stop}, # {#pause}, {#resume}, and {#save_state} to control the virtual machine. # Typically, you won't ever have to call this method and should # instead call those. # # @param [String] command The command to run on controlvm # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException} # will be raised if the command failed. # @return [Boolean] True if command was successful, false otherwise. def control(command, raise_errors=false) - Command.vboxmanage("controlvm #{@original_name} #{command}") + Command.vboxmanage("controlvm #{Command.shell_escape(@original_name)} #{command}") true rescue Exceptions::CommandFailedException raise if raise_errors false end - + # Destroys the virtual machine. This method also removes all attached # media (required by VirtualBox to destroy a VM). By default, # this **will not** destroy attached hard drives, but will if given # the `destroy_image` option. # @@ -384,10 +402,45 @@ # images, etc. def destroy(*args) # Call super first to destroy relationships, necessary before # unregistering a VM super - - Command.vboxmanage("unregistervm #{@original_name} --delete") + + Command.vboxmanage("unregistervm #{Command.shell_escape(@original_name)} --delete") + end + + # Returns true if the virtual machine state is running + # + # @return [Boolean] True if virtual machine state is running + def running? + state == 'running' + end + + # Returns true if the virtual machine state is powered off + # + # @return [Boolean] True if virtual machine state is powered off + def powered_off? + state == 'poweroff' + end + + # Returns true if the virtual machine state is paused + # + # @return [Boolean] True if virtual machine state is paused + def paused? + state == 'paused' + end + + # Returns true if the virtual machine state is saved + # + # @return [Boolean] True if virtual machine state is saved + def saved? + state == 'saved' + end + + # Returns true if the virtual machine state is aborted + # + # @return [Boolean] True if virtual machine state is aborted + def aborted? + state == 'aborted' end end end \ No newline at end of file