virtualbox 0.5.4 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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