virtualbox 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +1 -1
  3. data/Rakefile +1 -1
  4. data/Readme.md +5 -21
  5. data/VERSION +1 -1
  6. data/docs/WhatsNew.md +9 -47
  7. data/lib/virtualbox.rb +7 -30
  8. data/lib/virtualbox/abstract_model.rb +25 -5
  9. data/lib/virtualbox/abstract_model/attributable.rb +5 -1
  10. data/lib/virtualbox/abstract_model/dirty.rb +2 -0
  11. data/lib/virtualbox/abstract_model/interface_attributes.rb +96 -0
  12. data/lib/virtualbox/abstract_model/relatable.rb +19 -8
  13. data/lib/virtualbox/appliance.rb +59 -0
  14. data/lib/virtualbox/audio_adapter.rb +44 -0
  15. data/lib/virtualbox/bios.rb +44 -0
  16. data/lib/virtualbox/com.rb +23 -0
  17. data/lib/virtualbox/com/abstract_enum.rb +42 -0
  18. data/lib/virtualbox/com/abstract_implementer.rb +43 -0
  19. data/lib/virtualbox/com/abstract_interface.rb +165 -0
  20. data/lib/virtualbox/com/ffi/interface.rb +141 -0
  21. data/lib/virtualbox/com/ffi/interfaces.rb +42 -0
  22. data/lib/virtualbox/com/ffi/util.rb +101 -0
  23. data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
  24. data/lib/virtualbox/com/ffi_interface.rb +65 -0
  25. data/lib/virtualbox/com/implementer/base.rb +52 -0
  26. data/lib/virtualbox/com/implementer/ffi.rb +350 -0
  27. data/lib/virtualbox/com/implementer/mscom.rb +165 -0
  28. data/lib/virtualbox/com/implementer/nil.rb +10 -0
  29. data/lib/virtualbox/com/interface/appliance.rb +20 -0
  30. data/lib/virtualbox/com/interface/audio_adapter.rb +13 -0
  31. data/lib/virtualbox/com/interface/audio_controller_type.rb +9 -0
  32. data/lib/virtualbox/com/interface/audio_driver_type.rb +9 -0
  33. data/lib/virtualbox/com/interface/bios_boot_menu_mode.rb +9 -0
  34. data/lib/virtualbox/com/interface/bios_settings.rb +19 -0
  35. data/lib/virtualbox/com/interface/clipboard_mode.rb +9 -0
  36. data/lib/virtualbox/com/interface/console.rb +48 -0
  37. data/lib/virtualbox/com/interface/cpu_property_type.rb +9 -0
  38. data/lib/virtualbox/com/interface/device_type.rb +9 -0
  39. data/lib/virtualbox/com/interface/dhcp_server.rb +20 -0
  40. data/lib/virtualbox/com/interface/firmware_type.rb +9 -0
  41. data/lib/virtualbox/com/interface/guest_os_type.rb +21 -0
  42. data/lib/virtualbox/com/interface/host.rb +40 -0
  43. data/lib/virtualbox/com/interface/host_network_interface.rb +28 -0
  44. data/lib/virtualbox/com/interface/host_network_interface_medium_type.rb +9 -0
  45. data/lib/virtualbox/com/interface/host_network_interface_status.rb +9 -0
  46. data/lib/virtualbox/com/interface/host_network_interface_type.rb +9 -0
  47. data/lib/virtualbox/com/interface/host_usb_device.rb +11 -0
  48. data/lib/virtualbox/com/interface/host_usb_device_filter.rb +11 -0
  49. data/lib/virtualbox/com/interface/hw_virt_ex_property_type.rb +9 -0
  50. data/lib/virtualbox/com/interface/machine.rb +103 -0
  51. data/lib/virtualbox/com/interface/machine_state.rb +12 -0
  52. data/lib/virtualbox/com/interface/medium.rb +48 -0
  53. data/lib/virtualbox/com/interface/medium_attachment.rb +16 -0
  54. data/lib/virtualbox/com/interface/medium_format.rb +16 -0
  55. data/lib/virtualbox/com/interface/medium_state.rb +9 -0
  56. data/lib/virtualbox/com/interface/medium_type.rb +9 -0
  57. data/lib/virtualbox/com/interface/medium_variant.rb +9 -0
  58. data/lib/virtualbox/com/interface/network_adapter.rb +28 -0
  59. data/lib/virtualbox/com/interface/network_adapter_type.rb +9 -0
  60. data/lib/virtualbox/com/interface/network_attachment_type.rb +9 -0
  61. data/lib/virtualbox/com/interface/nsiexception.rb +21 -0
  62. data/lib/virtualbox/com/interface/nsisupports.rb +13 -0
  63. data/lib/virtualbox/com/interface/parallel_port.rb +15 -0
  64. data/lib/virtualbox/com/interface/port_mode.rb +9 -0
  65. data/lib/virtualbox/com/interface/progress.rb +58 -0
  66. data/lib/virtualbox/com/interface/serial_port.rb +17 -0
  67. data/lib/virtualbox/com/interface/session.rb +16 -0
  68. data/lib/virtualbox/com/interface/session_state.rb +9 -0
  69. data/lib/virtualbox/com/interface/session_type.rb +9 -0
  70. data/lib/virtualbox/com/interface/shared_folder.rb +15 -0
  71. data/lib/virtualbox/com/interface/snapshot.rb +18 -0
  72. data/lib/virtualbox/com/interface/storage_bus.rb +9 -0
  73. data/lib/virtualbox/com/interface/storage_controller.rb +21 -0
  74. data/lib/virtualbox/com/interface/storage_controller_type.rb +9 -0
  75. data/lib/virtualbox/com/interface/system_properties.rb +35 -0
  76. data/lib/virtualbox/com/interface/usb_controller.rb +18 -0
  77. data/lib/virtualbox/com/interface/usb_device.rb +22 -0
  78. data/lib/virtualbox/com/interface/usb_device_filter.rb +21 -0
  79. data/lib/virtualbox/com/interface/usb_device_filter_action.rb +9 -0
  80. data/lib/virtualbox/com/interface/usb_device_state.rb +9 -0
  81. data/lib/virtualbox/com/interface/virtual_box_error_info.rb +15 -0
  82. data/lib/virtualbox/com/interface/virtual_system_description.rb +17 -0
  83. data/lib/virtualbox/com/interface/virtual_system_description_type.rb +12 -0
  84. data/lib/virtualbox/com/interface/virtual_system_description_value_type.rb +9 -0
  85. data/lib/virtualbox/com/interface/virtualbox.rb +54 -0
  86. data/lib/virtualbox/com/interface/vrdp_auth_type.rb +9 -0
  87. data/lib/virtualbox/com/interface/vrdp_server.rb +17 -0
  88. data/lib/virtualbox/com/mscom_interface.rb +22 -0
  89. data/lib/virtualbox/com/util.rb +18 -0
  90. data/lib/virtualbox/dvd.rb +7 -94
  91. data/lib/virtualbox/exceptions.rb +24 -0
  92. data/lib/virtualbox/ext/glob_loader.rb +22 -0
  93. data/lib/virtualbox/ext/logger.rb +38 -0
  94. data/lib/virtualbox/ext/platform.rb +1 -1
  95. data/lib/virtualbox/extra_data.rb +25 -37
  96. data/lib/virtualbox/forwarded_port.rb +35 -13
  97. data/lib/virtualbox/global.rb +22 -80
  98. data/lib/virtualbox/hard_drive.rb +30 -97
  99. data/lib/virtualbox/lib.rb +82 -0
  100. data/lib/virtualbox/media.rb +7 -6
  101. data/lib/virtualbox/medium.rb +138 -0
  102. data/lib/virtualbox/medium_attachment.rb +61 -0
  103. data/lib/virtualbox/network_adapter.rb +134 -0
  104. data/lib/virtualbox/shared_folder.rb +53 -78
  105. data/lib/virtualbox/storage_controller.rb +76 -20
  106. data/lib/virtualbox/system_properties.rb +74 -0
  107. data/lib/virtualbox/usb_controller.rb +55 -0
  108. data/lib/virtualbox/version.rb +15 -0
  109. data/lib/virtualbox/virtual_system_description.rb +47 -0
  110. data/lib/virtualbox/vm.rb +160 -272
  111. data/test/test_helper.rb +0 -108
  112. data/test/virtualbox/abstract_model/attributable_test.rb +7 -1
  113. data/test/virtualbox/abstract_model/dirty_test.rb +1 -1
  114. data/test/virtualbox/abstract_model/interface_attributes_test.rb +169 -0
  115. data/test/virtualbox/abstract_model/relatable_test.rb +20 -0
  116. data/test/virtualbox/abstract_model_test.rb +40 -5
  117. data/test/virtualbox/appliance_test.rb +152 -0
  118. data/test/virtualbox/audio_adapter_test.rb +83 -0
  119. data/test/virtualbox/bios_test.rb +83 -0
  120. data/test/virtualbox/com/abstract_enum_test.rb +48 -0
  121. data/test/virtualbox/com/abstract_implementer_test.rb +39 -0
  122. data/test/virtualbox/com/abstract_interface_test.rb +139 -0
  123. data/test/virtualbox/com/ffi/interface_test.rb +249 -0
  124. data/test/virtualbox/com/ffi/util_test.rb +86 -0
  125. data/test/virtualbox/com/ffi_interface_test.rb +42 -0
  126. data/test/virtualbox/com/implementer/base_test.rb +37 -0
  127. data/test/virtualbox/com/implementer/ffi_test.rb +519 -0
  128. data/test/virtualbox/com/implementer/mscom_test.rb +208 -0
  129. data/test/virtualbox/com/mscom_interface_test.rb +17 -0
  130. data/test/virtualbox/com/util_test.rb +17 -0
  131. data/test/virtualbox/dvd_test.rb +4 -95
  132. data/test/virtualbox/ext/platform_test.rb +8 -0
  133. data/test/virtualbox/extra_data_test.rb +78 -102
  134. data/test/virtualbox/forwarded_port_test.rb +57 -7
  135. data/test/virtualbox/global_test.rb +25 -115
  136. data/test/virtualbox/hard_drive_test.rb +49 -212
  137. data/test/virtualbox/lib_test.rb +93 -0
  138. data/test/virtualbox/medium_attachment_test.rb +147 -0
  139. data/test/virtualbox/medium_test.rb +192 -0
  140. data/test/virtualbox/network_adapter_test.rb +160 -0
  141. data/test/virtualbox/shared_folder_test.rb +144 -160
  142. data/test/virtualbox/storage_controller_test.rb +166 -45
  143. data/test/virtualbox/system_properties_test.rb +87 -0
  144. data/test/virtualbox/usb_controller_test.rb +104 -0
  145. data/test/virtualbox/version_test.rb +34 -0
  146. data/test/virtualbox/virtual_system_description_test.rb +61 -0
  147. data/test/virtualbox/vm_test.rb +288 -322
  148. data/test/virtualbox_test.rb +1 -9
  149. data/virtualbox.gemspec +139 -23
  150. metadata +143 -27
  151. data/lib/virtualbox/attached_device.rb +0 -249
  152. data/lib/virtualbox/command.rb +0 -109
  153. data/lib/virtualbox/image.rb +0 -137
  154. data/lib/virtualbox/nic.rb +0 -111
  155. data/lib/virtualbox/system_property.rb +0 -55
  156. data/lib/virtualbox/usb.rb +0 -72
  157. data/test/virtualbox/attached_device_test.rb +0 -303
  158. data/test/virtualbox/command_test.rb +0 -152
  159. data/test/virtualbox/image_test.rb +0 -190
  160. data/test/virtualbox/nic_test.rb +0 -76
  161. data/test/virtualbox/system_property_test.rb +0 -71
  162. data/test/virtualbox/usb_test.rb +0 -35
@@ -0,0 +1,74 @@
1
+ module VirtualBox
2
+ # Represents the system properties associated with this VirtualBox
3
+ # installation. Many of these properties are readonly and represent
4
+ # limits on the system (max RAM available, max CPU, etc.). There are
5
+ # also configurable options which can be saved such as the default
6
+ # hard disk folder, or default machine folder.
7
+ class SystemProperties < AbstractModel
8
+ attribute :interface, :readonly => true, :property => false
9
+ attribute :min_guest_ram, :readonly => true
10
+ attribute :max_guest_ram, :readonly => true
11
+ attribute :min_guest_vram, :readonly => true
12
+ attribute :max_guest_vram, :readonly => true
13
+ attribute :min_guest_cpu_count, :readonly => true
14
+ attribute :max_guest_cpu_count, :readonly => true
15
+ attribute :max_vdi_size, :readonly => true
16
+ attribute :network_adapter_count, :readonly => true
17
+ attribute :serial_port_count, :readonly => true
18
+ attribute :parallel_port_count, :readonly => true
19
+ attribute :max_boot_position, :readonly => true
20
+ attribute :default_machine_folder
21
+ attribute :default_hard_disk_folder
22
+ attribute :medium_formats, :readonly => true
23
+ attribute :default_hard_disk_format
24
+ attribute :remote_display_auth_library
25
+ attribute :web_service_auth_library
26
+ attribute :log_history_count
27
+ attribute :default_audio_driver, :readonly => true
28
+
29
+ class <<self
30
+ # Populates the system properties relationship for anything
31
+ # which is related to it.
32
+ #
33
+ # **This method typically won't be used except internally.**
34
+ #
35
+ # @return [SystemProperties]
36
+ def populate_relationship(caller, data)
37
+ new(data)
38
+ end
39
+
40
+ # Saves the relationship. This simply calls {#save} on the
41
+ # relationship object.
42
+ #
43
+ # **This method typically won't be used except internally.**
44
+ def save_relationship(caller, item)
45
+ item.save
46
+ end
47
+ end
48
+
49
+ # Initializes the system properties object. This shouldn't be called
50
+ # directly. Instead `Global#system_properties` should be used to
51
+ # retrieve this object.
52
+ def initialize(isysprop)
53
+ initialize_attributes(isysprop)
54
+ end
55
+
56
+ # Initializes the attributes of an existing shared folder.
57
+ def initialize_attributes(isysprop)
58
+ # Save the interface to an attribute
59
+ write_attribute(:interface, isysprop)
60
+
61
+ # Load the attributes from the interface
62
+ load_interface_attributes(interface)
63
+
64
+ # Clear dirty and mark as existing
65
+ clear_dirty!
66
+ existing_record!
67
+ end
68
+
69
+ # Saves the system properties.
70
+ def save
71
+ save_changed_interface_attributes(interface)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,55 @@
1
+ module VirtualBox
2
+ # Represents a USB controller within VirtualBox. This class is a relationship
3
+ # to {VM} objects.
4
+ class USBController < AbstractModel
5
+ attribute :parent, :readonly => true, :property => false
6
+ attribute :interface, :readonly => true, :property => false
7
+ attribute :enabled
8
+ attribute :enabled_ehci
9
+ attribute :usb_standard, :readonly => true
10
+
11
+ class <<self
12
+ # Populates the USB controller relationship for anything
13
+ # which is related to it.
14
+ #
15
+ # **This method typically won't be used except internally.**
16
+ #
17
+ # @return [USBController]
18
+ def populate_relationship(caller, machine)
19
+ new(caller, machine.usb_controller)
20
+ end
21
+
22
+ # Saves the relationship. This simply calls {#save} on the
23
+ # relationship object.
24
+ #
25
+ # **This method typically won't be used except internally.**
26
+ def save_relationship(caller, item)
27
+ item.save
28
+ end
29
+ end
30
+
31
+ def initialize(parent, iusb)
32
+ initialize_attributes(parent, iusb)
33
+ end
34
+
35
+ def initialize_attributes(parent, iusb)
36
+ # Write the parent and interface attributes
37
+ write_attribute(:parent, parent)
38
+ write_attribute(:interface, iusb)
39
+
40
+ # Load the interface attributes
41
+ load_interface_attributes(interface)
42
+
43
+ # Clear dirty and mark as existing
44
+ clear_dirty!
45
+ existing_record!
46
+ end
47
+
48
+ # Saves the USB controller.
49
+ def save
50
+ parent.with_open_session do |session|
51
+ save_changed_interface_attributes(session.machine.usb_controller)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,15 @@
1
+ module VirtualBox
2
+ module Version
3
+ # Returns the version string of the VirtualBox installed, ex. "3.1.6"
4
+ def version
5
+ Lib.lib.virtualbox.version
6
+ rescue Exception
7
+ nil
8
+ end
9
+
10
+ # Returns the revision string of the VirtualBox installed, ex. "51742"
11
+ def revision
12
+ Lib.lib.virtualbox.revision
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,47 @@
1
+ module VirtualBox
2
+ # Represents a description of a virtual system in an {Appliance}. This contains
3
+ # the values that are in the OVF files as well as recommend values from VirtualBox.
4
+ class VirtualSystemDescription < AbstractModel
5
+ attribute :interface, :readonly => true
6
+ attribute :descriptions, :readonly => true, :default => {}
7
+
8
+ class <<self
9
+ def populate_relationship(caller, data)
10
+ result = Proxies::Collection.new(caller)
11
+
12
+ data.each do |vsd|
13
+ result << new(vsd)
14
+ end
15
+
16
+ result
17
+ end
18
+ end
19
+
20
+ def initialize(ivsd)
21
+ write_attribute(:interface, ivsd)
22
+ initialize_attributes(ivsd)
23
+ end
24
+
25
+ def initialize_attributes(ivsd)
26
+ # Grab all the descriptions, iterate over each, and add to the hash of
27
+ # descriptions. This multiple loop method is used instead of `get_description` since
28
+ # that method doesn't work well with MSCOM.
29
+ COM::Interface::VirtualSystemDescriptionType.each_with_index do |type, index|
30
+ COM::Interface::VirtualSystemDescriptionValueType.each_with_index do |value_type, value_index|
31
+ value = ivsd.get_values_by_type(type, value_type)
32
+ if value && value != [] && value != [nil]
33
+ descriptions[type] ||= {}
34
+ descriptions[type][value_type] = value.first
35
+ end
36
+ end
37
+ end
38
+
39
+ # Clear dirtiness, since this should only be called initially and
40
+ # therefore shouldn't affect dirtiness
41
+ clear_dirty!
42
+
43
+ # But this is an existing record
44
+ existing_record!
45
+ end
46
+ end
47
+ end
data/lib/virtualbox/vm.rb CHANGED
@@ -88,53 +88,53 @@ module VirtualBox
88
88
  # relationship :forwarded_ports, ForwardedPort
89
89
  #
90
90
  class VM < AbstractModel
91
- attribute :uuid, :readonly => true
91
+ attribute :uuid, :readonly => true, :property => :id
92
92
  attribute :name
93
- attribute :ostype
93
+ attribute :os_type_id
94
94
  attribute :description, :readonly => true
95
- attribute :memory
96
- attribute :vram
97
- attribute :acpi
98
- attribute :ioapic
99
- attribute :cpus
100
- attribute :synthcpu, :lazy => true
101
- attribute :pae
102
- attribute :hwvirtex
103
- attribute :hwvirtexexcl
104
- attribute :nestedpaging
105
- attribute :vtxvpid
106
- attribute :accelerate3d
107
- attribute :accelerate2dvideo
108
- attribute :biosbootmenu, :populate_key => :bootmenu
109
- attribute :boot1
110
- attribute :boot2
111
- attribute :boot3
112
- attribute :boot4
113
- attribute :clipboard
114
- attribute :monitorcount
115
- attribute :usb
116
- attribute :ehci
117
- attribute :audio
118
- attribute :audiocontroller
119
- attribute :audiodriver
120
- attribute :vrdp
121
- attribute :vrdpport
122
- attribute :vrdpauthtype
123
- attribute :vrdpauthtimeout
124
- attribute :state, :populate_key => :vmstate, :readonly => true, :lazy => true
125
- relationship :nics, Nic
126
- relationship :usbs, USB
127
- relationship :storage_controllers, StorageController, :dependent => :destroy
128
- relationship :shared_folders, SharedFolder
129
- relationship :extra_data, ExtraData
130
- relationship :forwarded_ports, ForwardedPort
95
+ attribute :memory_size
96
+ attribute :memory_balloon_size
97
+ attribute :vram_size
98
+ attribute :cpu_count
99
+ attribute :accelerate_3d_enabled
100
+ attribute :accelerate_2d_video_enabled
101
+ attribute :clipboard_mode
102
+ attribute :monitor_count
103
+ attribute :state, :readonly => true
104
+ attribute :accessible, :readonly => true
105
+ attribute :hardware_version
106
+ attribute :hardware_uuid
107
+ attribute :statistics_update_interval
108
+ attribute :firmware_type
109
+ attribute :snapshot_folder
110
+ attribute :settings_file_path, :readonly => true
111
+ attribute :last_state_change, :readonly => true
112
+ attribute :state_file_path, :readonly => true
113
+ attribute :log_folder, :readonly => true
114
+ attribute :snapshot_count, :readonly => true
115
+ attribute :current_state_modified, :readonly => true
116
+ attribute :guest_property_notification_patterns
117
+ attribute :teleporter_enabled
118
+ attribute :teleporter_port
119
+ attribute :teleporter_address
120
+ attribute :teleporter_password
121
+ attribute :interface, :readonly => true, :property => false
122
+ relationship :audio_adapter, :AudioAdapter
123
+ relationship :bios, :BIOS
124
+ relationship :storage_controllers, :StorageController, :dependent => :destroy
125
+ relationship :medium_attachments, :MediumAttachment
126
+ relationship :shared_folders, :SharedFolder
127
+ relationship :extra_data, :ExtraData
128
+ relationship :forwarded_ports, :ForwardedPort
129
+ relationship :network_adapters, :NetworkAdapter
130
+ relationship :usb_controller, :USBController
131
131
 
132
132
  class <<self
133
133
  # Returns an array of all available VMs.
134
134
  #
135
135
  # @return [Array<VM>]
136
- def all(reload=false)
137
- Global.global(reload).vms
136
+ def all
137
+ Global.global(true).vms
138
138
  end
139
139
 
140
140
  # Finds a VM by UUID or registered name and returns a
@@ -142,20 +142,7 @@ module VirtualBox
142
142
  #
143
143
  # @return [VM]
144
144
  def find(name)
145
- all(true).detect { |o| o.name == name || o.uuid == name }
146
- end
147
-
148
- # Loads a VM from its XML configuration file. All VMs managed
149
- # by VirtualBox have an XML configuration file somewhere. If
150
- # given the path, this will instantiate the VM that way. Typically
151
- # this method will only be called internally. Users of the class
152
- # should use {all} or {find} instead.
153
- #
154
- # @param [String] location Full path to the XML file.
155
- # @return [VM]
156
- def load_from_xml(location)
157
- vm_doc = Command.parse_xml(location)
158
- new(vm_doc)
145
+ all.detect { |o| o.name == name || o.uuid == name }
159
146
  end
160
147
 
161
148
  # Imports a VM, blocking the entire thread during this time.
@@ -163,68 +150,27 @@ module VirtualBox
163
150
  # VM object can be used to make any modifications necessary
164
151
  # (RAM, cpus, etc.).
165
152
  #
166
- # @return [VM] The newly imported virtual machine
167
- def import(source_path)
168
- raw = Command.vboxmanage("import", source_path)
169
- return nil unless raw
170
-
171
- find(parse_vm_name(raw))
172
- end
173
-
174
- # Gets the VM info (machine readable) for a given VM and returns it
175
- # as a hash.
176
- #
177
- # @return [Hash] Parsed VM info.
178
- def raw_info(name)
179
- raw = Command.vboxmanage("showvminfo", name, "--machinereadable")
180
- parse_vm_info(raw)
181
- end
182
-
183
- # Parses the machine-readable format outputted by VBoxManage showvminfo
184
- # into a hash. Ignores lines which don't match the format.
185
- def parse_vm_info(raw)
186
- parsed = {}
187
- raw.split("\n").each do |line|
188
- # Some lines aren't configuration, we just ignore them
189
- next unless line =~ /^"?(.+?)"?="?(.+?)"?$/
190
- parsed[$1.downcase.to_sym] = $2.strip
191
- end
192
-
193
- parsed
194
- end
195
-
196
- # Parses the list of VMs returned by the "list vms" command used
197
- # in {VM.all}.
153
+ # If there are multiple VMs in the OVF file being imported,
154
+ # the first virtual machine will be returned, although all will
155
+ # be imported.
198
156
  #
199
- # **This method typically won't be used except internally.**
157
+ # If a block is given, it will be yielded with the percent of the
158
+ # import operation, so that the progress of the import can be
159
+ # tracked.
200
160
  #
201
- # @return [Array] Array of virtual machines.
202
- def parse_vm_list(raw)
203
- results = []
204
- raw.split("\n").each do |line|
205
- next unless line =~ /^"(.+?)"\s+\{(.+?)\}$/
206
- results.push(find($1.to_s))
207
- end
208
-
209
- results
210
- end
161
+ # @return [VM] The newly imported virtual machine
162
+ def import(source_path, &block)
163
+ appliance = Appliance.new(source_path)
164
+ appliance.import(&block)
211
165
 
212
- # Parses the vm name from the import results.
213
- #
214
- # **This method typically won't be used except internally.**
215
- #
216
- # @return [String] Parsed VM name
217
- def parse_vm_name(raw)
218
- return nil unless raw =~ /VM name "(.+?)"/
219
- $1.to_s
166
+ find(appliance.virtual_systems.first.descriptions[:name][:auto])
220
167
  end
221
168
 
222
- def populate_relationship(caller, doc)
169
+ def populate_relationship(caller, machines)
223
170
  result = Proxies::Collection.new(caller)
224
171
 
225
- doc.css("Global MachineRegistry MachineEntry").each do |entry|
226
- location = Global.expand_path(entry[:src])
227
- result << load_from_xml(location)
172
+ machines.each do |machine|
173
+ result << new(machine)
228
174
  end
229
175
 
230
176
  result
@@ -237,62 +183,19 @@ module VirtualBox
237
183
  # Support for creating new virtual machines will be added shortly.
238
184
  # For now, this is only used by {VM.find} and {VM.all} to
239
185
  # initialize the VMs.
240
- def initialize(data)
186
+ def initialize(imachine)
241
187
  super()
242
188
 
243
- initialize_attributes(data)
244
- populate_relationships(data)
245
- @original_name = name
189
+ write_attribute(:interface, imachine)
190
+ initialize_attributes(imachine)
246
191
  end
247
192
 
248
- def initialize_attributes(doc)
249
- attribute_associations = {
250
- :uuid => ["Machine", :uuid],
251
- :name => ["Machine", :name],
252
- :ostype => ["Machine", :OSType],
253
- :description => ["Machine Description"],
254
- :memory => ["Hardware Memory", :RAMSize],
255
- :vram => ["Hardware Display", :VRAMSize],
256
- :acpi => ["Hardware BIOS ACPI", :enabled],
257
- :ioapic => ["Hardware BIOS IOAPIC", :enabled],
258
- :cpus => ["Hardware CPU", :count],
259
- :pae => ["Hardware CPU PAE", :enabled],
260
- :hwvirtex => ["Hardware CPU HardwareVirtEx", :enabled],
261
- :hwvirtexexcl => ["Hardware CPU HardwareVirtEx", :exclusive],
262
- :nestedpaging => ["Hardware CPU HardwareVirtExNestedPaging", :enabled],
263
- :vtxvpid => ["Hardware CPU HardwareVirtExVPID", :enabled],
264
- :accelerate3d => ["Hardware Display", :accelerate3D],
265
- :accelerate2dvideo => ["Hardware Display", :accelerate2DVideo],
266
- :biosbootmenu => ["Hardware BIOS BootMenu", :mode],
267
- :boot1 => ["Hardware Boot Order[position=\"1\"]", :device],
268
- :boot2 => ["Hardware Boot Order[position=\"2\"]", :device],
269
- :boot3 => ["Hardware Boot Order[position=\"3\"]", :device],
270
- :boot4 => ["Hardware Boot Order[position=\"4\"]", :device],
271
- :clipboard => ["Hardware Clipboard", :mode],
272
- :monitorcount => ["Hardware Display", :monitorCount],
273
- :usb => ["Hardware USBController", :enabled],
274
- :ehci => ["Hardware USBController", :enabledEhci],
275
- :audio => ["Hardware AudioAdapter", :enabled],
276
- :audiocontroller => ["Hardware AudioAdapter", :controller],
277
- :audiodriver => ["Hardware AudioAdapter", :driver],
278
- :vrdp => ["Hardware RemoteDisplay", :enabled],
279
- :vrdpport => ["Hardware RemoteDisplay", :port],
280
- :vrdpauthtype => ["Hardware RemoteDisplay", :authType],
281
- :vrdpauthtimeout => ["Hardware RemoteDisplay", :authTimeout],
282
- }
283
-
284
- attribute_associations.each do |name, search_data|
285
- css, key = search_data
286
- node = doc.css(css)[0]
287
-
288
- # key is passed in for attributes, else you get the element inner text
289
- value = (key ? node[key] : node.inner_text) if node
290
-
291
- # Special cases
292
- value = value[1..-2] if name == :uuid
293
-
294
- write_attribute(name, value)
295
- end
193
+ def initialize_attributes(machine)
194
+ # Load the interface attributes
195
+ load_interface_attributes(machine)
196
+
197
+ # Setup the relationships
198
+ populate_relationships(machine)
296
199
 
297
200
  # Clear dirtiness, since this should only be called initially and
298
201
  # therefore shouldn't affect dirtiness
@@ -302,13 +205,6 @@ module VirtualBox
302
205
  existing_record!
303
206
  end
304
207
 
305
- def load_attribute(name)
306
- info = self.class.raw_info(@original_name)
307
-
308
- write_attribute(:state, info[:vmstate]) if name == :state
309
- write_attribute(:synthcpu, info[:synthcpu]) unless loaded_attribute?(:synthcpu)
310
- end
311
-
312
208
  # State of the virtual machine. Returns the state of the virtual
313
209
  # machine. This state will represent the state that was assigned
314
210
  # when the VM was found unless `reload` is set to `true`.
@@ -318,7 +214,7 @@ module VirtualBox
318
214
  # @return [String] Virtual machine state.
319
215
  def state(reload=false)
320
216
  if reload
321
- load_attribute(:state)
217
+ load_interface_attribute(:state)
322
218
  clear_dirty!(:state)
323
219
  end
324
220
 
@@ -328,34 +224,50 @@ module VirtualBox
328
224
  # Saves the virtual machine if modified. This method saves any modified
329
225
  # attributes of the virtual machine. If any related attributes were saved
330
226
  # as well (such as storage controllers), those will be saved, too.
331
- def save(raise_errors=false)
332
- if changed?
333
- # First save all the changed attributes in a single batch
334
- saves = changes.inject([]) do |acc, kv|
335
- key, values = kv
336
- acc << ["--#{key}", values[1]]
337
- end
227
+ def save
228
+ with_open_session do |session|
229
+ # Use setters to save the attributes on the locked machine and persist
230
+ # the settings
231
+ machine = session.machine
232
+
233
+ # Save all the attributes and relationships
234
+ save_changed_interface_attributes(machine)
235
+
236
+ # Save relationships, which may open their own sessions if necessary
237
+ save_relationships
238
+ end
239
+ end
240
+
241
+ # Opens a direct session with the machine this VM represents and yields
242
+ # the session object to a block. Many of the VirtualBox's settings can only
243
+ # be modified with an open session on a machine. An open session is similar
244
+ # to a write-lock. Once the session is completed, it must be closed, which
245
+ # this method does as well.
246
+ def with_open_session
247
+ # Set the session up
248
+ session = Lib.lib.session
338
249
 
339
- # Flatten to pass into vboxmanage
340
- saves.flatten!
250
+ close_session = false
341
251
 
342
- # Save all the attributes in one command
343
- Command.vboxmanage("modifyvm", @original_name, *saves)
252
+ if session.state != :open
253
+ # Open up a session for this virtual machine
254
+ interface.parent.open_session(session, uuid)
344
255
 
345
- # Now clear attributes and call super so relationships are saved
346
- @original_name = name
347
- clear_dirty!
256
+ # Mark the session to be closed
257
+ close_session = true
348
258
  end
349
259
 
350
- super()
260
+ # Yield the block with the session
261
+ yield session
351
262
 
352
- # Force reload
353
- Global.reload!
263
+ # Close the session
264
+ if close_session
265
+ # Save these settings only if we're closing
266
+ session.machine.save_settings
354
267
 
355
- true
356
- rescue Exceptions::CommandFailedException
357
- raise if raise_errors
358
- return false
268
+ # Close the session
269
+ session.close
270
+ end
359
271
  end
360
272
 
361
273
  # Exports a virtual machine. The virtual machine will be exported
@@ -370,51 +282,42 @@ module VirtualBox
370
282
  # This method will block until the export is complete, which takes about
371
283
  # 60 to 90 seconds on my 2.2 GHz 2009 model MacBook Pro.
372
284
  #
285
+ # If a block is given to the method, then it will be yielded with the
286
+ # percent progress of the operation (in intervals of 1 percent).
287
+ #
373
288
  # @param [String] filename The file (not directory) to save the exported
374
289
  # OVF file. This directory will also receive the checksum file and
375
290
  # virtual disks.
376
- # @option options [String] :product (nil) The name of the product
377
- # @option options [String] :producturl (nil) The URL of the product
378
- # @option options [String] :vendor (nil) The name of the vendor
379
- # @option options [String] :vendorurl (nil) The URL for the vendor
380
- # @option options [String] :version (nil) The version information
381
- # @option options [String] :eula (nil) License text
382
- # @option options [String] :eulafile (nil) License file
383
- def export(filename, options={}, raise_error=false)
384
- options = options.inject([]) do |acc, kv|
385
- acc.push("--#{kv[0]}")
386
- acc.push(kv[1])
387
- end
388
-
389
- options.unshift("0").unshift("--vsys") unless options.empty?
390
-
391
- raw = Command.vboxmanage("export", @original_name, "-o", filename, *options)
392
- true
393
- rescue Exceptions::CommandFailedException
394
- raise if raise_error
395
- false
291
+ def export(filename, &block)
292
+ app = Appliance.new
293
+ app.path = filename
294
+ app.add_machine(self)
295
+ app.export(&block)
396
296
  end
397
297
 
398
298
  # Starts the virtual machine. The virtual machine can be started in a
399
299
  # variety of modes:
400
300
  #
401
301
  # * **gui** -- The VirtualBox GUI will open with the screen of the VM.
402
- # * **headless** -- The VM will run in the background. No GUI will be
302
+ # * **vrdp** -- The VM will run in the background. No GUI will be
403
303
  # present at all.
404
304
  #
405
- # All modes will start their processes and return almost immediately.
406
- # Both the GUI and headless mode will not block the ruby process.
305
+ # This method blocks while the external processes are starting.
407
306
  #
408
307
  # @param [Symbol] mode Described above.
409
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
410
- # will be raised if the command failed.
411
308
  # @return [Boolean] True if command was successful, false otherwise.
412
- def start(mode=:gui, raise_errors=false)
413
- Command.vboxmanage("startvm", @original_name, "--type", mode)
309
+ def start(mode="gui")
310
+ return false if running?
311
+
312
+ # Open a new remote session, this will automatically start the machine
313
+ # as well
314
+ session = Lib.lib.session
315
+ interface.parent.open_remote_session(session, uuid, mode.to_s, "").wait_for_completion(-1)
316
+
317
+ # Close our session to release our lock from the machine
318
+ session.close
319
+
414
320
  true
415
- rescue Exceptions::CommandFailedException
416
- raise if raise_errors
417
- false
418
321
  end
419
322
 
420
323
  # Shuts down the VM by directly calling "acpipowerbutton". Depending on the
@@ -422,65 +325,49 @@ module VirtualBox
422
325
  # installations don't respond to the ACPI power button at all. In such cases,
423
326
  # {#stop} or {#save_state} may be used instead.
424
327
  #
425
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
426
- # will be raised if the command failed.
427
328
  # @return [Boolean] True if command was successful, false otherwise.
428
- def shutdown(raise_errors=false)
429
- control(:acpipowerbutton, raise_errors)
329
+ def shutdown
330
+ control(:power_button)
430
331
  end
431
332
 
432
333
  # Stops the VM by directly calling "poweroff." Immediately halts the
433
334
  # virtual machine without saving state. This could result in a loss
434
335
  # of data. To prevent data loss, see {#shutdown}
435
336
  #
436
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
437
- # will be raised if the command failed.
438
337
  # @return [Boolean] True if command was successful, false otherwise.
439
- def stop(raise_errors=false)
440
- control(:poweroff, raise_errors)
338
+ def stop
339
+ control(:power_down)
441
340
  end
442
341
 
443
342
  # Pauses the VM, putting it on hold temporarily. The VM can be resumed
444
343
  # again by calling {#resume}
445
344
  #
446
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
447
- # will be raised if the command failed.
448
345
  # @return [Boolean] True if command was successful, false otherwise.
449
- def pause(raise_errors=false)
450
- control(:pause, raise_errors)
346
+ def pause
347
+ control(:pause)
451
348
  end
452
349
 
453
350
  # Resume a paused VM.
454
351
  #
455
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
456
- # will be raised if the command failed.
457
352
  # @return [Boolean] True if command was successful, false otherwise.
458
- def resume(raise_errors=false)
459
- control(:resume, raise_errors)
353
+ def resume
354
+ control(:resume)
460
355
  end
461
356
 
462
357
  # Saves the state of a VM and stops it. The VM can be resumed
463
358
  # again by calling "{#start}" again.
464
359
  #
465
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
466
- # will be raised if the command failed.
467
360
  # @return [Boolean] True if command was successful, false otherwise.
468
- def save_state(raise_errors=false)
469
- control(:savestate, raise_errors)
361
+ def save_state
362
+ control(:save_state)
470
363
  end
471
364
 
472
365
  # Discards any saved state on the current VM. The VM is not destroyed though
473
366
  # and can still be started by calling {#start}.
474
367
  #
475
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
476
- # will be raised if the command failed.
477
368
  # @return [Boolean] True if command was successful, false otherwise.
478
- def discard_state(raise_errors=false)
479
- Command.vboxmanage("discardstate", @original_name)
480
- true
481
- rescue Exceptions::CommandFailedException
482
- raise if raise_errors
483
- false
369
+ def discard_state
370
+ control(:forget_saved_state, true)
484
371
  end
485
372
 
486
373
  # Controls the virtual machine. This method is used by {#stop},
@@ -489,15 +376,18 @@ module VirtualBox
489
376
  # instead call those.
490
377
  #
491
378
  # @param [String] command The command to run on controlvm
492
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
493
- # will be raised if the command failed.
494
379
  # @return [Boolean] True if command was successful, false otherwise.
495
- def control(command, raise_errors=false)
496
- Command.vboxmanage("controlvm", @original_name, command)
497
- true
498
- rescue Exceptions::CommandFailedException
499
- raise if raise_errors
500
- false
380
+ def control(command, *args)
381
+ # Grab the session using an existing session
382
+ session = Lib.lib.session
383
+ interface.parent.open_existing_session(session, uuid)
384
+
385
+ # Send the proper command, waiting if we have to
386
+ result = session.console.send(command, *args)
387
+ result.wait_for_completion(-1) if result.is_a?(COM::Interface::Progress)
388
+
389
+ # Close the session
390
+ session.close
501
391
  end
502
392
 
503
393
  # Destroys the virtual machine. This method also removes all attached
@@ -507,55 +397,53 @@ module VirtualBox
507
397
  #
508
398
  # @overload destroy(opts = {})
509
399
  # Passes options to the destroy method.
510
- # @option opts [Boolean] :destroy_image (false) If true, will
511
- # also destroy all attached images such as hard drives, disk
512
- # images, etc.
400
+ # @option opts [Boolean] :destroy_medium (false) If true, will
401
+ # also unregister attached media. If set to `:delete`, it will
402
+ # not only unregister attached media, but will also physically
403
+ # remove their respective data.
513
404
  def destroy(*args)
514
- # Call super first to destroy relationships, necessary before
515
- # unregistering a VM
405
+ # Call super first so destroy is propogated through to relationships
406
+ # first
516
407
  super
517
408
 
518
- if Command.vboxmanage("unregistervm", @original_name, "--delete")
519
- Global.reload!
520
- return true
521
- else
522
- return false
523
- end
409
+ # Finally, destroy this machine and remove the settings file
410
+ interface.parent.unregister_machine(uuid)
411
+ interface.delete_settings
524
412
  end
525
413
 
526
414
  # Returns true if the virtual machine state is running
527
415
  #
528
416
  # @return [Boolean] True if virtual machine state is running
529
417
  def running?
530
- state == 'running'
418
+ state == :running
531
419
  end
532
420
 
533
421
  # Returns true if the virtual machine state is powered off
534
422
  #
535
423
  # @return [Boolean] True if virtual machine state is powered off
536
424
  def powered_off?
537
- state == 'poweroff'
425
+ state == :powered_off
538
426
  end
539
427
 
540
428
  # Returns true if the virtual machine state is paused
541
429
  #
542
430
  # @return [Boolean] True if virtual machine state is paused
543
431
  def paused?
544
- state == 'paused'
432
+ state == :paused
545
433
  end
546
434
 
547
435
  # Returns true if the virtual machine state is saved
548
436
  #
549
437
  # @return [Boolean] True if virtual machine state is saved
550
438
  def saved?
551
- state == 'saved'
439
+ state == :saved
552
440
  end
553
441
 
554
442
  # Returns true if the virtual machine state is aborted
555
443
  #
556
444
  # @return [Boolean] True if virtual machine state is aborted
557
445
  def aborted?
558
- state == 'aborted'
446
+ state == :aborted
559
447
  end
560
448
  end
561
449
  end