bbrowning-virtualbox 0.7.6.dev

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 (281) hide show
  1. data/.gitignore +8 -0
  2. data/.yardopts +3 -0
  3. data/Gemfile +16 -0
  4. data/LICENSE +19 -0
  5. data/Rakefile +33 -0
  6. data/Readme.md +70 -0
  7. data/docs/GettingStarted.md +196 -0
  8. data/docs/WhatsNew.md +12 -0
  9. data/features/README.md +33 -0
  10. data/features/global.feature +19 -0
  11. data/features/global_extra_data.feature +27 -0
  12. data/features/step_definitions/abstract_model_steps.rb +39 -0
  13. data/features/step_definitions/extra_data_steps.rb +36 -0
  14. data/features/step_definitions/global_steps.rb +29 -0
  15. data/features/step_definitions/nat_engine_steps.rb +76 -0
  16. data/features/step_definitions/network_adapter_steps.rb +38 -0
  17. data/features/step_definitions/shared_folder_steps.rb +76 -0
  18. data/features/step_definitions/snapshot_steps.rb +74 -0
  19. data/features/step_definitions/storage_controller_steps.rb +16 -0
  20. data/features/step_definitions/virtualbox_steps.rb +17 -0
  21. data/features/step_definitions/vm_steps.rb +50 -0
  22. data/features/support/env.rb +61 -0
  23. data/features/support/helpers.rb +38 -0
  24. data/features/support/hooks.rb +30 -0
  25. data/features/support/ordered_hash.rb +49 -0
  26. data/features/support/vboxmanage.rb +191 -0
  27. data/features/version.feature +16 -0
  28. data/features/vm.feature +13 -0
  29. data/features/vm_bios.feature +29 -0
  30. data/features/vm_cpu.feature +29 -0
  31. data/features/vm_extra_data.feature +35 -0
  32. data/features/vm_hw_virt.feature +29 -0
  33. data/features/vm_nat_engine.feature +57 -0
  34. data/features/vm_network_adapters.feature +27 -0
  35. data/features/vm_shared_folders.feature +42 -0
  36. data/features/vm_snapshots.feature +29 -0
  37. data/features/vm_storage_controllers.feature +11 -0
  38. data/lib/virtualbox.rb +11 -0
  39. data/lib/virtualbox/abstract_model.rb +281 -0
  40. data/lib/virtualbox/abstract_model/attributable.rb +290 -0
  41. data/lib/virtualbox/abstract_model/dirty.rb +177 -0
  42. data/lib/virtualbox/abstract_model/interface_attributes.rb +98 -0
  43. data/lib/virtualbox/abstract_model/relatable.rb +332 -0
  44. data/lib/virtualbox/abstract_model/validatable.rb +167 -0
  45. data/lib/virtualbox/abstract_model/version_matcher.rb +35 -0
  46. data/lib/virtualbox/appliance.rb +62 -0
  47. data/lib/virtualbox/audio_adapter.rb +52 -0
  48. data/lib/virtualbox/bios.rb +50 -0
  49. data/lib/virtualbox/com.rb +23 -0
  50. data/lib/virtualbox/com/abstract_enum.rb +43 -0
  51. data/lib/virtualbox/com/abstract_implementer.rb +45 -0
  52. data/lib/virtualbox/com/abstract_interface.rb +167 -0
  53. data/lib/virtualbox/com/base_interface.rb +38 -0
  54. data/lib/virtualbox/com/ffi/interface.rb +150 -0
  55. data/lib/virtualbox/com/ffi/interfaces.rb +54 -0
  56. data/lib/virtualbox/com/ffi/util.rb +119 -0
  57. data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
  58. data/lib/virtualbox/com/ffi_interface.rb +96 -0
  59. data/lib/virtualbox/com/implementer/base.rb +59 -0
  60. data/lib/virtualbox/com/implementer/ffi.rb +361 -0
  61. data/lib/virtualbox/com/implementer/mscom.rb +175 -0
  62. data/lib/virtualbox/com/implementer/nil.rb +10 -0
  63. data/lib/virtualbox/com/interface/3.1.x/access_mode.rb +11 -0
  64. data/lib/virtualbox/com/interface/3.1.x/appliance.rb +22 -0
  65. data/lib/virtualbox/com/interface/3.1.x/audio_adapter.rb +15 -0
  66. data/lib/virtualbox/com/interface/3.1.x/audio_controller_type.rb +11 -0
  67. data/lib/virtualbox/com/interface/3.1.x/audio_driver_type.rb +11 -0
  68. data/lib/virtualbox/com/interface/3.1.x/bios_boot_menu_mode.rb +11 -0
  69. data/lib/virtualbox/com/interface/3.1.x/bios_settings.rb +21 -0
  70. data/lib/virtualbox/com/interface/3.1.x/clipboard_mode.rb +11 -0
  71. data/lib/virtualbox/com/interface/3.1.x/console.rb +50 -0
  72. data/lib/virtualbox/com/interface/3.1.x/cpu_property_type.rb +11 -0
  73. data/lib/virtualbox/com/interface/3.1.x/device_type.rb +11 -0
  74. data/lib/virtualbox/com/interface/3.1.x/dhcp_server.rb +22 -0
  75. data/lib/virtualbox/com/interface/3.1.x/firmware_type.rb +11 -0
  76. data/lib/virtualbox/com/interface/3.1.x/guest_os_type.rb +23 -0
  77. data/lib/virtualbox/com/interface/3.1.x/host.rb +42 -0
  78. data/lib/virtualbox/com/interface/3.1.x/host_network_interface.rb +30 -0
  79. data/lib/virtualbox/com/interface/3.1.x/host_network_interface_medium_type.rb +11 -0
  80. data/lib/virtualbox/com/interface/3.1.x/host_network_interface_status.rb +11 -0
  81. data/lib/virtualbox/com/interface/3.1.x/host_network_interface_type.rb +11 -0
  82. data/lib/virtualbox/com/interface/3.1.x/host_usb_device.rb +13 -0
  83. data/lib/virtualbox/com/interface/3.1.x/host_usb_device_filter.rb +13 -0
  84. data/lib/virtualbox/com/interface/3.1.x/hw_virt_ex_property_type.rb +11 -0
  85. data/lib/virtualbox/com/interface/3.1.x/machine.rb +105 -0
  86. data/lib/virtualbox/com/interface/3.1.x/machine_state.rb +14 -0
  87. data/lib/virtualbox/com/interface/3.1.x/medium.rb +50 -0
  88. data/lib/virtualbox/com/interface/3.1.x/medium_attachment.rb +18 -0
  89. data/lib/virtualbox/com/interface/3.1.x/medium_format.rb +18 -0
  90. data/lib/virtualbox/com/interface/3.1.x/medium_state.rb +11 -0
  91. data/lib/virtualbox/com/interface/3.1.x/medium_type.rb +11 -0
  92. data/lib/virtualbox/com/interface/3.1.x/medium_variant.rb +11 -0
  93. data/lib/virtualbox/com/interface/3.1.x/network_adapter.rb +30 -0
  94. data/lib/virtualbox/com/interface/3.1.x/network_adapter_type.rb +11 -0
  95. data/lib/virtualbox/com/interface/3.1.x/network_attachment_type.rb +11 -0
  96. data/lib/virtualbox/com/interface/3.1.x/nsiexception.rb +23 -0
  97. data/lib/virtualbox/com/interface/3.1.x/nsisupports.rb +15 -0
  98. data/lib/virtualbox/com/interface/3.1.x/parallel_port.rb +17 -0
  99. data/lib/virtualbox/com/interface/3.1.x/port_mode.rb +11 -0
  100. data/lib/virtualbox/com/interface/3.1.x/progress.rb +63 -0
  101. data/lib/virtualbox/com/interface/3.1.x/serial_port.rb +19 -0
  102. data/lib/virtualbox/com/interface/3.1.x/session.rb +18 -0
  103. data/lib/virtualbox/com/interface/3.1.x/session_state.rb +11 -0
  104. data/lib/virtualbox/com/interface/3.1.x/session_type.rb +11 -0
  105. data/lib/virtualbox/com/interface/3.1.x/shared_folder.rb +17 -0
  106. data/lib/virtualbox/com/interface/3.1.x/snapshot.rb +20 -0
  107. data/lib/virtualbox/com/interface/3.1.x/storage_bus.rb +11 -0
  108. data/lib/virtualbox/com/interface/3.1.x/storage_controller.rb +23 -0
  109. data/lib/virtualbox/com/interface/3.1.x/storage_controller_type.rb +11 -0
  110. data/lib/virtualbox/com/interface/3.1.x/system_properties.rb +37 -0
  111. data/lib/virtualbox/com/interface/3.1.x/usb_controller.rb +20 -0
  112. data/lib/virtualbox/com/interface/3.1.x/usb_device.rb +24 -0
  113. data/lib/virtualbox/com/interface/3.1.x/usb_device_filter.rb +23 -0
  114. data/lib/virtualbox/com/interface/3.1.x/usb_device_filter_action.rb +11 -0
  115. data/lib/virtualbox/com/interface/3.1.x/usb_device_state.rb +11 -0
  116. data/lib/virtualbox/com/interface/3.1.x/virtual_box_error_info.rb +17 -0
  117. data/lib/virtualbox/com/interface/3.1.x/virtual_system_description.rb +19 -0
  118. data/lib/virtualbox/com/interface/3.1.x/virtual_system_description_type.rb +14 -0
  119. data/lib/virtualbox/com/interface/3.1.x/virtual_system_description_value_type.rb +11 -0
  120. data/lib/virtualbox/com/interface/3.1.x/virtualbox.rb +67 -0
  121. data/lib/virtualbox/com/interface/3.1.x/vrdp_auth_type.rb +11 -0
  122. data/lib/virtualbox/com/interface/3.1.x/vrdp_server.rb +19 -0
  123. data/lib/virtualbox/com/interface/3.2.x/access_mode.rb +11 -0
  124. data/lib/virtualbox/com/interface/3.2.x/appliance.rb +22 -0
  125. data/lib/virtualbox/com/interface/3.2.x/audio_adapter.rb +15 -0
  126. data/lib/virtualbox/com/interface/3.2.x/audio_controller_type.rb +11 -0
  127. data/lib/virtualbox/com/interface/3.2.x/audio_driver_type.rb +11 -0
  128. data/lib/virtualbox/com/interface/3.2.x/bios_boot_menu_mode.rb +11 -0
  129. data/lib/virtualbox/com/interface/3.2.x/bios_settings.rb +21 -0
  130. data/lib/virtualbox/com/interface/3.2.x/clipboard_mode.rb +11 -0
  131. data/lib/virtualbox/com/interface/3.2.x/console.rb +50 -0
  132. data/lib/virtualbox/com/interface/3.2.x/cpu_property_type.rb +11 -0
  133. data/lib/virtualbox/com/interface/3.2.x/device_type.rb +11 -0
  134. data/lib/virtualbox/com/interface/3.2.x/dhcp_server.rb +22 -0
  135. data/lib/virtualbox/com/interface/3.2.x/firmware_type.rb +11 -0
  136. data/lib/virtualbox/com/interface/3.2.x/guest.rb +13 -0
  137. data/lib/virtualbox/com/interface/3.2.x/guest_os_type.rb +33 -0
  138. data/lib/virtualbox/com/interface/3.2.x/host.rb +43 -0
  139. data/lib/virtualbox/com/interface/3.2.x/host_network_interface.rb +30 -0
  140. data/lib/virtualbox/com/interface/3.2.x/host_network_interface_medium_type.rb +11 -0
  141. data/lib/virtualbox/com/interface/3.2.x/host_network_interface_status.rb +11 -0
  142. data/lib/virtualbox/com/interface/3.2.x/host_network_interface_type.rb +11 -0
  143. data/lib/virtualbox/com/interface/3.2.x/host_usb_device.rb +13 -0
  144. data/lib/virtualbox/com/interface/3.2.x/host_usb_device_filter.rb +13 -0
  145. data/lib/virtualbox/com/interface/3.2.x/hw_virt_ex_property_type.rb +11 -0
  146. data/lib/virtualbox/com/interface/3.2.x/keyboard_hid_type.rb +11 -0
  147. data/lib/virtualbox/com/interface/3.2.x/machine.rb +118 -0
  148. data/lib/virtualbox/com/interface/3.2.x/machine_state.rb +14 -0
  149. data/lib/virtualbox/com/interface/3.2.x/medium.rb +51 -0
  150. data/lib/virtualbox/com/interface/3.2.x/medium_attachment.rb +18 -0
  151. data/lib/virtualbox/com/interface/3.2.x/medium_format.rb +18 -0
  152. data/lib/virtualbox/com/interface/3.2.x/medium_state.rb +11 -0
  153. data/lib/virtualbox/com/interface/3.2.x/medium_type.rb +11 -0
  154. data/lib/virtualbox/com/interface/3.2.x/medium_variant.rb +11 -0
  155. data/lib/virtualbox/com/interface/3.2.x/nat_alias_mode.rb +11 -0
  156. data/lib/virtualbox/com/interface/3.2.x/nat_engine.rb +27 -0
  157. data/lib/virtualbox/com/interface/3.2.x/nat_protocol.rb +11 -0
  158. data/lib/virtualbox/com/interface/3.2.x/network_adapter.rb +34 -0
  159. data/lib/virtualbox/com/interface/3.2.x/network_adapter_type.rb +11 -0
  160. data/lib/virtualbox/com/interface/3.2.x/network_attachment_type.rb +11 -0
  161. data/lib/virtualbox/com/interface/3.2.x/nsiexception.rb +23 -0
  162. data/lib/virtualbox/com/interface/3.2.x/nsisupports.rb +15 -0
  163. data/lib/virtualbox/com/interface/3.2.x/parallel_port.rb +17 -0
  164. data/lib/virtualbox/com/interface/3.2.x/pointing_hid_type.rb +11 -0
  165. data/lib/virtualbox/com/interface/3.2.x/port_mode.rb +11 -0
  166. data/lib/virtualbox/com/interface/3.2.x/progress.rb +63 -0
  167. data/lib/virtualbox/com/interface/3.2.x/serial_port.rb +19 -0
  168. data/lib/virtualbox/com/interface/3.2.x/session.rb +18 -0
  169. data/lib/virtualbox/com/interface/3.2.x/session_state.rb +11 -0
  170. data/lib/virtualbox/com/interface/3.2.x/session_type.rb +11 -0
  171. data/lib/virtualbox/com/interface/3.2.x/shared_folder.rb +17 -0
  172. data/lib/virtualbox/com/interface/3.2.x/snapshot.rb +20 -0
  173. data/lib/virtualbox/com/interface/3.2.x/storage_bus.rb +11 -0
  174. data/lib/virtualbox/com/interface/3.2.x/storage_controller.rb +24 -0
  175. data/lib/virtualbox/com/interface/3.2.x/storage_controller_type.rb +11 -0
  176. data/lib/virtualbox/com/interface/3.2.x/system_properties.rb +42 -0
  177. data/lib/virtualbox/com/interface/3.2.x/usb_controller.rb +21 -0
  178. data/lib/virtualbox/com/interface/3.2.x/usb_device.rb +24 -0
  179. data/lib/virtualbox/com/interface/3.2.x/usb_device_filter.rb +23 -0
  180. data/lib/virtualbox/com/interface/3.2.x/usb_device_filter_action.rb +11 -0
  181. data/lib/virtualbox/com/interface/3.2.x/usb_device_state.rb +11 -0
  182. data/lib/virtualbox/com/interface/3.2.x/virtual_box_error_info.rb +17 -0
  183. data/lib/virtualbox/com/interface/3.2.x/virtual_system_description.rb +19 -0
  184. data/lib/virtualbox/com/interface/3.2.x/virtual_system_description_type.rb +14 -0
  185. data/lib/virtualbox/com/interface/3.2.x/virtual_system_description_value_type.rb +11 -0
  186. data/lib/virtualbox/com/interface/3.2.x/virtualbox.rb +67 -0
  187. data/lib/virtualbox/com/interface/3.2.x/vrdp_auth_type.rb +11 -0
  188. data/lib/virtualbox/com/interface/3.2.x/vrdp_server.rb +21 -0
  189. data/lib/virtualbox/com/mscom_interface.rb +44 -0
  190. data/lib/virtualbox/com/nil_interface.rb +7 -0
  191. data/lib/virtualbox/com/util.rb +32 -0
  192. data/lib/virtualbox/cpu.rb +61 -0
  193. data/lib/virtualbox/dhcp_server.rb +89 -0
  194. data/lib/virtualbox/dvd.rb +27 -0
  195. data/lib/virtualbox/exceptions.rb +39 -0
  196. data/lib/virtualbox/ext/byte_normalizer.rb +17 -0
  197. data/lib/virtualbox/ext/glob_loader.rb +22 -0
  198. data/lib/virtualbox/ext/logger.rb +38 -0
  199. data/lib/virtualbox/ext/platform.rb +27 -0
  200. data/lib/virtualbox/ext/subclass_listing.rb +24 -0
  201. data/lib/virtualbox/extra_data.rb +127 -0
  202. data/lib/virtualbox/forwarded_port.rb +222 -0
  203. data/lib/virtualbox/global.rb +102 -0
  204. data/lib/virtualbox/guest_property.rb +116 -0
  205. data/lib/virtualbox/hard_drive.rb +246 -0
  206. data/lib/virtualbox/host.rb +71 -0
  207. data/lib/virtualbox/host_network_interface.rb +137 -0
  208. data/lib/virtualbox/hw_virtualization.rb +63 -0
  209. data/lib/virtualbox/lib.rb +84 -0
  210. data/lib/virtualbox/media.rb +20 -0
  211. data/lib/virtualbox/medium.rb +145 -0
  212. data/lib/virtualbox/medium_attachment.rb +61 -0
  213. data/lib/virtualbox/nat_engine.rb +71 -0
  214. data/lib/virtualbox/nat_forwarded_port.rb +171 -0
  215. data/lib/virtualbox/network_adapter.rb +166 -0
  216. data/lib/virtualbox/proxies/collection.rb +57 -0
  217. data/lib/virtualbox/shared_folder.rb +220 -0
  218. data/lib/virtualbox/snapshot.rb +185 -0
  219. data/lib/virtualbox/storage_controller.rb +160 -0
  220. data/lib/virtualbox/system_properties.rb +74 -0
  221. data/lib/virtualbox/usb_controller.rb +59 -0
  222. data/lib/virtualbox/usb_device_filter.rb +74 -0
  223. data/lib/virtualbox/version.rb +36 -0
  224. data/lib/virtualbox/virtual_system_description.rb +47 -0
  225. data/lib/virtualbox/vm.rb +684 -0
  226. data/lib/virtualbox/vrdp_server.rb +59 -0
  227. data/test/test_helper.rb +18 -0
  228. data/test/virtualbox/abstract_model/attributable_test.rb +269 -0
  229. data/test/virtualbox/abstract_model/dirty_test.rb +83 -0
  230. data/test/virtualbox/abstract_model/interface_attributes_test.rb +194 -0
  231. data/test/virtualbox/abstract_model/relatable_test.rb +348 -0
  232. data/test/virtualbox/abstract_model/validatable_test.rb +308 -0
  233. data/test/virtualbox/abstract_model/version_matcher_test.rb +41 -0
  234. data/test/virtualbox/abstract_model_test.rb +462 -0
  235. data/test/virtualbox/appliance_test.rb +159 -0
  236. data/test/virtualbox/audio_adapter_test.rb +83 -0
  237. data/test/virtualbox/bios_test.rb +83 -0
  238. data/test/virtualbox/com/abstract_enum_test.rb +49 -0
  239. data/test/virtualbox/com/abstract_implementer_test.rb +40 -0
  240. data/test/virtualbox/com/abstract_interface_test.rb +140 -0
  241. data/test/virtualbox/com/ffi/interface_test.rb +249 -0
  242. data/test/virtualbox/com/ffi/util_test.rb +108 -0
  243. data/test/virtualbox/com/ffi_interface_test.rb +42 -0
  244. data/test/virtualbox/com/implementer/base_test.rb +38 -0
  245. data/test/virtualbox/com/implementer/ffi_test.rb +527 -0
  246. data/test/virtualbox/com/implementer/mscom_test.rb +247 -0
  247. data/test/virtualbox/com/mscom_interface_test.rb +17 -0
  248. data/test/virtualbox/com/util_test.rb +17 -0
  249. data/test/virtualbox/cpu_test.rb +103 -0
  250. data/test/virtualbox/dhcp_server_test.rb +165 -0
  251. data/test/virtualbox/dvd_test.rb +28 -0
  252. data/test/virtualbox/ext/byte_normalizer_test.rb +34 -0
  253. data/test/virtualbox/ext/platform_test.rb +50 -0
  254. data/test/virtualbox/ext/subclass_listing_test.rb +25 -0
  255. data/test/virtualbox/extra_data_test.rb +155 -0
  256. data/test/virtualbox/forwarded_port_test.rb +286 -0
  257. data/test/virtualbox/global_test.rb +46 -0
  258. data/test/virtualbox/hard_drive_test.rb +141 -0
  259. data/test/virtualbox/host_network_interface_test.rb +254 -0
  260. data/test/virtualbox/host_test.rb +94 -0
  261. data/test/virtualbox/hw_virtualization_test.rb +103 -0
  262. data/test/virtualbox/lib_test.rb +93 -0
  263. data/test/virtualbox/medium_attachment_test.rb +147 -0
  264. data/test/virtualbox/medium_test.rb +192 -0
  265. data/test/virtualbox/nat_engine_test.rb +106 -0
  266. data/test/virtualbox/nat_forwarded_port_test.rb +222 -0
  267. data/test/virtualbox/network_adapter_test.rb +191 -0
  268. data/test/virtualbox/proxies/collection_test.rb +102 -0
  269. data/test/virtualbox/shared_folder_test.rb +219 -0
  270. data/test/virtualbox/snapshot_test.rb +231 -0
  271. data/test/virtualbox/storage_controller_test.rb +197 -0
  272. data/test/virtualbox/system_properties_test.rb +87 -0
  273. data/test/virtualbox/usb_controller_test.rb +112 -0
  274. data/test/virtualbox/usb_device_filter_test.rb +93 -0
  275. data/test/virtualbox/version_test.rb +59 -0
  276. data/test/virtualbox/virtual_system_description_test.rb +61 -0
  277. data/test/virtualbox/vm_test.rb +637 -0
  278. data/test/virtualbox/vrdp_server_test.rb +83 -0
  279. data/test/virtualbox_test.rb +11 -0
  280. data/virtualbox.gemspec +25 -0
  281. metadata +397 -0
@@ -0,0 +1,684 @@
1
+ module VirtualBox
2
+ # Represents a single VirtualBox virtual machine. All attributes which are
3
+ # not read-only can be modified and saved.
4
+ #
5
+ # # Finding Virtual Machines
6
+ #
7
+ # Two methods are used to find virtual machines: {VM.all} and {VM.find}. Each
8
+ # return a {VM} object. An example is shown below:
9
+ #
10
+ # vm = VirtualBox::VM.find("MyWindowsXP")
11
+ # puts vm.name # => "MyWindowsXP"
12
+ #
13
+ # # Modifying Virtual Machines
14
+ #
15
+ # Virtual machines can be modified a lot like [ActiveRecord](http://ar.rubyonrails.org/)
16
+ # objects. This is best shown through example:
17
+ #
18
+ # vm = VirtualBox::VM.find("MyWindowsXP")
19
+ # vm.memory_size = 256
20
+ # vm.name = "WindowsXP"
21
+ # vm.save
22
+ #
23
+ # # Controlling Virtual Machines
24
+ #
25
+ # Virtual machines can be controlled using the basic {#start}, {#stop}, etc.
26
+ # methods. The current state of the VM can also be retrieved via the {#state}
27
+ # method. An example of this use is shown below:
28
+ #
29
+ # if vm.powered_off?
30
+ # vm.start
31
+ # end
32
+ #
33
+ # # Taking a Snapshot
34
+ #
35
+ # Snapshots allow virtual machine states to be saved at a given point in time
36
+ # without having to stop the machine. This state can then be restored later.
37
+ # VirtualBox handles this by creating a differencing image which allows the hard
38
+ # drive to even retain its exact state. Taking a snapshot is extremely simple:
39
+ #
40
+ # vm = VirtualBox::VM.find("MyWindowsXP")
41
+ # vm.take_snapshot("My Snapshot", "A description of my snapshot")
42
+ #
43
+ # # Traversing Snapshots
44
+ #
45
+ # Snapshots are represented by a tree-like structure. There is a root snapshot
46
+ # and that snapshot has many children which may in turn have their own children.
47
+ # The easiest way to traverse this structure is to use the {#root_snapshot}
48
+ # VM method and traverse the structure like any tree structure:
49
+ #
50
+ # vm = VirtualBox::VM.find("MyWindowsXP")
51
+ # p vm.root_snapshot.children.length
52
+ #
53
+ # # Finding Snapshots
54
+ #
55
+ # While traversing the entire snapshot tree can be useful, it is often more
56
+ # useful to be able to simply find a snapshot by name. For this, use the
57
+ # {#find_snapshot} method:
58
+ #
59
+ # vm = VirtualBox::VM.find("MyWindowsXP")
60
+ # p vm.find_snapshot("PreSP3")
61
+ #
62
+ # # Attributes and Relationships
63
+ #
64
+ # Properties of the virtual machine are exposed using standard ruby instance
65
+ # methods which are generated on the fly. Because of this, they are not listed
66
+ # below as available instance methods.
67
+ #
68
+ # These attributes can be accessed and modified via standard ruby-style
69
+ # `instance.attribute` and `instance.attribute=` methods. The attributes are
70
+ # listed below.
71
+ #
72
+ # Relationships are also accessed like attributes but can't be set. Instead,
73
+ # they are typically references to other objects such as a {HardDrive} which
74
+ # in turn have their own attributes which can be modified.
75
+ #
76
+ # ## Attributes
77
+ #
78
+ # This is copied directly from the class header, but lists all available
79
+ # attributes. If you don't understand what this means, read {Attributable}.
80
+ #
81
+ # attribute :uuid, :readonly => true, :property => :id
82
+ # attribute :name
83
+ # attribute :os_type_id
84
+ # attribute :description
85
+ # attribute :memory_size
86
+ # attribute :memory_balloon_size
87
+ # attribute :vram_size
88
+ # attribute :cpu_count
89
+ # attribute :accelerate_3d_enabled, :boolean => true
90
+ # attribute :accelerate_2d_video_enabled, :boolean => true
91
+ # attribute :clipboard_mode
92
+ # attribute :monitor_count
93
+ # attribute :state, :readonly => true
94
+ # attribute :accessible, :readonly => true, :boolean => true
95
+ # attribute :hardware_version
96
+ # attribute :hardware_uuid
97
+ # attribute :firmware_type
98
+ # attribute :snapshot_folder
99
+ # attribute :settings_file_path, :readonly => true
100
+ # attribute :last_state_change, :readonly => true
101
+ # attribute :state_file_path, :readonly => true
102
+ # attribute :log_folder, :readonly => true
103
+ # attribute :snapshot_count, :readonly => true
104
+ # attribute :current_state_modified, :readonly => true
105
+ # attribute :guest_property_notification_patterns
106
+ # attribute :teleporter_enabled, :boolean => true
107
+ # attribute :teleporter_port
108
+ # attribute :teleporter_address
109
+ # attribute :teleporter_password
110
+ # attribute :interface, :readonly => true, :property => false
111
+ #
112
+ # ## Relationships
113
+ #
114
+ # In addition to the basic attributes, a virtual machine is related
115
+ # to other things. The relationships are listed below. If you don't
116
+ # understand this, read {Relatable}.
117
+ #
118
+ # relationship :audio_adapter, :AudioAdapter
119
+ # relationship :bios, :BIOS
120
+ # relationship :hw_virt, :HWVirtualization
121
+ # relationship :cpu, :CPU
122
+ # relationship :vrdp_server, :VRDPServer
123
+ # relationship :storage_controllers, :StorageController, :dependent => :destroy
124
+ # relationship :medium_attachments, :MediumAttachment
125
+ # relationship :shared_folders, :SharedFolder
126
+ # relationship :extra_data, :ExtraData
127
+ # relationship :guest_property, :GuestProperty
128
+ # relationship :forwarded_ports, :ForwardedPort
129
+ # relationship :network_adapters, :NetworkAdapter
130
+ # relationship :usb_controller, :USBController
131
+ # relationship :current_snapshot, :Snapshot
132
+ #
133
+ class VM < AbstractModel
134
+ attribute :uuid, :readonly => true, :property => :id
135
+ attribute :name
136
+ attribute :os_type_id
137
+ attribute :description
138
+ attribute :memory_size
139
+ attribute :memory_balloon_size
140
+ attribute :vram_size
141
+ attribute :cpu_count
142
+ attribute :accelerate_3d_enabled, :boolean => true
143
+ attribute :accelerate_2d_video_enabled, :boolean => true
144
+ attribute :clipboard_mode
145
+ attribute :monitor_count
146
+ attribute :state, :readonly => true
147
+ attribute :accessible, :readonly => true, :boolean => true
148
+ attribute :hardware_version
149
+ attribute :hardware_uuid
150
+ # TODO: Removed in 3.2.x, how should we handle this?
151
+ # attribute :statistics_update_interval
152
+ attribute :firmware_type
153
+ attribute :snapshot_folder
154
+ attribute :settings_file_path, :readonly => true
155
+ attribute :last_state_change, :readonly => true
156
+ attribute :state_file_path, :readonly => true
157
+ attribute :log_folder, :readonly => true
158
+ attribute :snapshot_count, :readonly => true
159
+ attribute :current_state_modified, :readonly => true
160
+ attribute :guest_property_notification_patterns
161
+ attribute :teleporter_enabled, :boolean => true
162
+ attribute :teleporter_port
163
+ attribute :teleporter_address
164
+ attribute :teleporter_password
165
+ attribute :boot_order,
166
+ :property_getter => Proc.new { |instance, *args| instance.get_boot_order(*args) },
167
+ :property_setter => Proc.new { |instance, *args| instance.set_boot_order(*args) }
168
+ attribute :interface, :readonly => true, :property => false
169
+ relationship :audio_adapter, :AudioAdapter
170
+ relationship :bios, :BIOS
171
+ relationship :hw_virt, :HWVirtualization
172
+ relationship :cpu, :CPU
173
+ relationship :vrdp_server, :VRDPServer
174
+ relationship :storage_controllers, :StorageController, :dependent => :destroy
175
+ relationship :medium_attachments, :MediumAttachment
176
+ relationship :shared_folders, :SharedFolder
177
+ relationship :extra_data, :ExtraData
178
+ relationship :guest_property, :GuestProperty
179
+ relationship :forwarded_ports, :ForwardedPort, :version => "3.1"
180
+ relationship :network_adapters, :NetworkAdapter
181
+ relationship :usb_controller, :USBController
182
+ relationship :current_snapshot, :Snapshot
183
+
184
+ class << self
185
+ # Returns an array of all available VMs.
186
+ #
187
+ # @return [Array<VM>]
188
+ def all
189
+ Global.global(true).vms
190
+ end
191
+
192
+ # Finds a VM by UUID or registered name and returns a
193
+ # new VM object. If the VM doesn't exist, will return `nil`.
194
+ #
195
+ # @return [VM]
196
+ def find(name)
197
+ all.detect { |o| o.name == name || o.uuid == name }
198
+ end
199
+
200
+ def create(name, type)
201
+ Global.global(true).create_machine(name, type)
202
+ end
203
+
204
+ # Imports a VM, blocking the entire thread during this time.
205
+ # When finished, on success, will return the VM object. This
206
+ # VM object can be used to make any modifications necessary
207
+ # (RAM, cpus, etc.).
208
+ #
209
+ # If there are multiple VMs in the OVF file being imported,
210
+ # the first virtual machine will be returned, although all will
211
+ # be imported.
212
+ #
213
+ # If a block is given, it will be yielded with the progress of the
214
+ # import operation, so that the progress of the import can be
215
+ # tracked.
216
+ #
217
+ # @return [VM] The newly imported virtual machine
218
+ def import(source_path, &block)
219
+ appliance = Appliance.new(source_path)
220
+ appliance.import(&block)
221
+
222
+ find(appliance.virtual_systems.first.descriptions[:name][:auto])
223
+ end
224
+
225
+ def populate_relationship(caller, machines)
226
+ machines.is_a?(Array) ? populate_array_relationship(caller, machines) : populate_single_relationship(caller, machines)
227
+ end
228
+
229
+ def populate_single_relationship(caller, machine)
230
+ new(machine)
231
+ end
232
+
233
+ def populate_array_relationship(caller, machines)
234
+ result = Proxies::Collection.new(caller)
235
+
236
+ machines.each do |machine|
237
+ result << new(machine)
238
+ end
239
+
240
+ result
241
+ end
242
+ end
243
+
244
+ # Creates a new instance of a virtual machine.
245
+ #
246
+ # **Currently can NOT be used to create a NEW virtual machine**.
247
+ # Support for creating new virtual machines will be added shortly.
248
+ # For now, this is only used by {VM.find} and {VM.all} to
249
+ # initialize the VMs.
250
+ def initialize(imachine)
251
+ super()
252
+
253
+ write_attribute(:interface, imachine)
254
+ initialize_attributes(imachine)
255
+ end
256
+
257
+ def initialize_attributes(machine)
258
+ # Load the interface attributes
259
+ load_interface_attributes(machine)
260
+
261
+ # Setup the relationships
262
+ populate_relationships(machine)
263
+
264
+ # Clear dirtiness, since this should only be called initially and
265
+ # therefore shouldn't affect dirtiness
266
+ clear_dirty!
267
+
268
+ # But this is an existing record
269
+ existing_record!
270
+ end
271
+
272
+ # Reload the model so that all the attributes and relationships are
273
+ # up to date. This method will automatically discard any changes to
274
+ # the VM and any of its relationships.
275
+ def reload
276
+ initialize_attributes(interface)
277
+ self
278
+ end
279
+
280
+ # State of the virtual machine. Returns the state of the virtual
281
+ # machine. This state will represent the state that was assigned
282
+ # when the VM was found unless `reload` is set to `true`.
283
+ #
284
+ # @param [Boolean] reload If true, will reload the state to current
285
+ # value.
286
+ # @return [String] Virtual machine state.
287
+ def state(suppress_state_reload=false)
288
+ if !suppress_state_reload
289
+ load_interface_attribute(:state, interface)
290
+ clear_dirty!(:state)
291
+ end
292
+
293
+ read_attribute(:state)
294
+ end
295
+
296
+ # Validates the virtual machine
297
+ def validate
298
+ super
299
+
300
+ validates_presence_of :name, :os_type_id, :memory_size, :vram_size, :cpu_count
301
+ validates_numericality_of :memory_balloon_size, :monitor_count
302
+ validates_inclusion_of :accelerate_3d_enabled, :accelerate_2d_video_enabled, :teleporter_enabled, :in => [true, false]
303
+
304
+ if !errors_on(:name)
305
+ # Only validate the name if the name has no errors already
306
+ vms_of_same_name = self.class.find(name)
307
+ add_error(:name, 'must not be used by another virtual machine.') if vms_of_same_name && vms_of_same_name.uuid != uuid
308
+ end
309
+
310
+ validates_inclusion_of :os_type_id, :in => VirtualBox::Global.global.lib.virtualbox.guest_os_types.collect { |os| os.id }
311
+
312
+ min_guest_ram, max_guest_ram = Global.global.system_properties.min_guest_ram, Global.global.system_properties.max_guest_ram
313
+ validates_inclusion_of :memory_size, :in => (min_guest_ram..max_guest_ram), :message => "must be between #{min_guest_ram} and #{max_guest_ram}."
314
+ validates_inclusion_of :memory_balloon_size, :in => (0..max_guest_ram), :message => "must be between 0 and #{max_guest_ram}."
315
+
316
+ min_guest_vram, max_guest_vram = Global.global.system_properties.min_guest_vram, Global.global.system_properties.max_guest_vram
317
+ validates_inclusion_of :vram_size, :in => (min_guest_vram..max_guest_vram), :message => "must be between #{min_guest_vram} and #{max_guest_vram}."
318
+
319
+ min_guest_cpu_count, max_guest_cpu_count = Global.global.system_properties.min_guest_cpu_count, Global.global.system_properties.max_guest_cpu_count
320
+ validates_inclusion_of :cpu_count, :in => (min_guest_cpu_count..max_guest_cpu_count), :message => "must be between #{min_guest_cpu_count} and #{max_guest_cpu_count}."
321
+
322
+ validates_inclusion_of :clipboard_mode, :in => COM::Util.versioned_interface(:ClipboardMode).map
323
+ validates_inclusion_of :firmware_type, :in => COM::Util.versioned_interface(:FirmwareType).map
324
+ end
325
+
326
+ # Saves the virtual machine if modified. This method saves any modified
327
+ # attributes of the virtual machine. If any related attributes were saved
328
+ # as well (such as storage controllers), those will be saved, too.
329
+ def save
330
+ return false unless valid?
331
+ raise Exceptions::ReadonlyVMStateException.new("VM must not be in saved state to modify.") if saved?
332
+
333
+ with_open_session do |session|
334
+ # Use setters to save the attributes on the locked machine and persist
335
+ # the settings
336
+ machine = session.machine
337
+
338
+ # Save the boot order
339
+ save_interface_attribute(:boot_order, machine)
340
+
341
+ # Save all the attributes and relationships
342
+ save_changed_interface_attributes(machine)
343
+
344
+ # Save relationships, which may open their own sessions if necessary
345
+ save_relationships
346
+ end
347
+
348
+ true
349
+ end
350
+
351
+ # Returns the root snapshot of this virtual machine. This root snapshot
352
+ # can be used to traverse the tree of snapshots.
353
+ #
354
+ # @return [Snapshot]
355
+ def root_snapshot
356
+ return nil if current_snapshot.nil?
357
+
358
+ current = current_snapshot
359
+ current = current.parent while current.parent != nil
360
+ current
361
+ end
362
+
363
+ # Find a snapshot by name or UUID. This allows you to find a snapshot by a given
364
+ # name, rather than having to resort to traversing the entire tree structure
365
+ # manually.
366
+ def find_snapshot(name)
367
+ find_helper = lambda do |name, root|
368
+ return nil if root.nil?
369
+ return root if root.name == name || root.uuid == name
370
+
371
+ root.children.each do |child|
372
+ result = find_helper.call(name, child)
373
+ return result unless result.nil?
374
+ end
375
+
376
+ nil
377
+ end
378
+
379
+ find_helper.call(name, root_snapshot)
380
+ end
381
+
382
+ # Opens a direct session with the machine this VM represents and yields
383
+ # the session object to a block. Many of the VirtualBox's settings can only
384
+ # be modified with an open session on a machine. An open session is similar
385
+ # to a write-lock. Once the session is completed, it must be closed, which
386
+ # this method does as well.
387
+ def with_open_session
388
+ # Set the session up
389
+ session = Lib.lib.session
390
+
391
+ close_session = false
392
+
393
+ if session.state != :open
394
+ # Open up a session for this virtual machine
395
+ interface.parent.open_session(session, uuid)
396
+
397
+ # Mark the session to be closed
398
+ close_session = true
399
+ end
400
+
401
+ # Yield the block with the session
402
+ yield session
403
+
404
+ # Close the session
405
+ if close_session
406
+ # Save these settings only if we're closing and only if the state
407
+ # is not saved, since that doesn't allow the machine to be saved.
408
+ session.machine.save_settings if session.machine.state != :saved
409
+
410
+ # Close the session
411
+ session.close
412
+ end
413
+ rescue Exception
414
+ # Close the session so we don't get locked out. We use a rescue block
415
+ # here instead of an "ensure" since we ONLY want this to occur if an
416
+ # exception is raised. Otherwise, we may or may not close the session,
417
+ # depending how deeply nested this call to `with_open_session` is.
418
+ # (see close_session boolean above)
419
+ session.close if session.state == :open
420
+
421
+ # Reraise the exception, we're not actually catching it to handle it
422
+ raise
423
+ end
424
+
425
+ # Exports a virtual machine. The virtual machine will be exported
426
+ # to the specified OVF file name. This directory will also have the
427
+ # `mf` file which contains the file checksums and also the virtual
428
+ # drives of the machine.
429
+ #
430
+ # Export also supports an additional options hash which can contain
431
+ # information that will be embedded with the virtual machine. View
432
+ # below for more information on the available options.
433
+ #
434
+ # This method will block until the export is complete, which takes about
435
+ # 60 to 90 seconds on my 2.2 GHz 2009 model MacBook Pro.
436
+ #
437
+ # If a block is given to the method, then it will be yielded with the
438
+ # progress of the operation.
439
+ #
440
+ # @param [String] filename The file (not directory) to save the exported
441
+ # OVF file. This directory will also receive the checksum file and
442
+ # virtual disks.
443
+ def export(filename, options = {}, &block)
444
+ app = Appliance.new
445
+ app.path = filename
446
+ app.add_machine(self, options)
447
+ app.export(&block)
448
+ end
449
+
450
+ # Take a snapshot of the current state of the machine. This method can be
451
+ # called while the VM is running and also while it is powered off. This
452
+ # method will block while the snapshot is being taken.
453
+ #
454
+ # If a block is given to this method, it will yield with a progress
455
+ # object which can be used to get the progress of the operation.
456
+ #
457
+ # @param [String] name Name of the snapshot.
458
+ # @param [String] description Description of the snapshot.
459
+ def take_snapshot(name, description="", &block)
460
+ with_open_session do |session|
461
+ session.console.take_snapshot(name, description).wait(&block)
462
+ end
463
+ end
464
+
465
+ # Starts the virtual machine. The virtual machine can be started in a
466
+ # variety of modes:
467
+ #
468
+ # * **gui** -- The VirtualBox GUI will open with the screen of the VM.
469
+ # * **vrdp** -- The VM will run in the background. No GUI will be
470
+ # present at all.
471
+ #
472
+ # This method blocks while the external processes are starting.
473
+ #
474
+ # @param [Symbol] mode Described above.
475
+ # @return [Boolean] True if command was successful, false otherwise.
476
+ def start(mode="gui")
477
+ return false if running?
478
+
479
+ # Open a new remote session, this will automatically start the machine
480
+ # as well
481
+ session = Lib.lib.session
482
+ interface.parent.open_remote_session(session, uuid, mode.to_s, "").wait_for_completion(-1)
483
+ true
484
+ ensure
485
+ # Be sure to close that session!
486
+ session.close if session && session.state == :open
487
+ end
488
+
489
+ # Shuts down the VM by directly calling "acpipowerbutton". Depending on the
490
+ # settings of the Virtual Machine, this may not work. For example, some linux
491
+ # installations don't respond to the ACPI power button at all. In such cases,
492
+ # {#stop} or {#save_state} may be used instead.
493
+ #
494
+ # @return [Boolean] True if command was successful, false otherwise.
495
+ def shutdown
496
+ control(:power_button)
497
+ end
498
+
499
+ # Stops the VM by directly calling "poweroff." Immediately halts the
500
+ # virtual machine without saving state. This could result in a loss
501
+ # of data. To prevent data loss, see {#shutdown}
502
+ #
503
+ # @return [Boolean] True if command was successful, false otherwise.
504
+ def stop
505
+ control(:power_down)
506
+ end
507
+
508
+ # Pauses the VM, putting it on hold temporarily. The VM can be resumed
509
+ # again by calling {#resume}
510
+ #
511
+ # @return [Boolean] True if command was successful, false otherwise.
512
+ def pause
513
+ control(:pause)
514
+ end
515
+
516
+ # Resume a paused VM.
517
+ #
518
+ # @return [Boolean] True if command was successful, false otherwise.
519
+ def resume
520
+ control(:resume)
521
+ end
522
+
523
+ # Saves the state of a VM and stops it. The VM can be resumed
524
+ # again by calling "{#start}" again.
525
+ #
526
+ # @return [Boolean] True if command was successful, false otherwise.
527
+ def save_state
528
+ control(:save_state)
529
+ end
530
+
531
+ # Discards any saved state on the current VM. The VM is not destroyed though
532
+ # and can still be started by calling {#start}.
533
+ #
534
+ # @return [Boolean] True if command was successful, false otherwise.
535
+ def discard_state
536
+ # Since the VM should be saved as it is, we don't open an
537
+ # existing session like the other control methods. We open a new
538
+ # session.
539
+ with_open_session do |session|
540
+ session.console.forget_saved_state(true)
541
+ end
542
+ end
543
+
544
+ # Controls the virtual machine. This method is used by {#stop},
545
+ # {#pause}, {#resume}, and {#save_state} to control the virtual machine.
546
+ # Typically, you won't ever have to call this method and should
547
+ # instead call those.
548
+ #
549
+ # @param [String] command The command to run on controlvm
550
+ # @return [Boolean] True if command was successful, false otherwise.
551
+ def control(command, *args)
552
+ # Grab the session using an existing session
553
+ session = Lib.lib.session
554
+ interface.parent.open_existing_session(session, uuid)
555
+
556
+ # Send the proper command, waiting if we have to
557
+ result = session.console.send(command, *args)
558
+ result.wait_for_completion(-1) if result.is_a?(COM::Util.versioned_interface(:Progress))
559
+ ensure
560
+ # Close the session
561
+ session.close if session && session.state == :open
562
+ end
563
+
564
+ # Destroys the virtual machine. This method also removes all attached
565
+ # media (required by VirtualBox to destroy a VM). By default,
566
+ # this **will not** destroy attached hard drives, but will if given
567
+ # the `destroy_image` option.
568
+ #
569
+ # @overload destroy(opts = {})
570
+ # Passes options to the destroy method.
571
+ # @option opts [Boolean] :destroy_medium (false) If true, will
572
+ # also unregister attached media. If set to `:delete`, it will
573
+ # not only unregister attached media, but will also physically
574
+ # remove their respective data.
575
+ def destroy(*args)
576
+ # Destroy all snapshots first (by destroying the root, all children
577
+ # are automatically destroyed)
578
+ if root_snapshot
579
+ destroy_snapshot = lambda do |snapshot|
580
+ return if snapshot.nil?
581
+
582
+ snapshot.children.each { |c| destroy_snapshot.call(c) }
583
+ snapshot.destroy
584
+ end
585
+
586
+ destroy_snapshot.call(root_snapshot)
587
+
588
+ # Reload ourselves before continuing since snapshots do some
589
+ # crazy things.
590
+ reload
591
+ end
592
+
593
+ # Call super first so destroy is propogated through to relationships
594
+ # first
595
+ super
596
+
597
+ # Finally, destroy this machine and remove the settings file
598
+ interface.parent.unregister_machine(uuid)
599
+ interface.delete_settings
600
+ end
601
+
602
+ # Returns true if the virtual machine state is starting
603
+ #
604
+ # @return [Boolean] True if virtual machine state is starting
605
+ def starting?
606
+ state == :starting
607
+ end
608
+
609
+ # Returns true if the virtual machine state is running
610
+ #
611
+ # @return [Boolean] True if virtual machine state is running
612
+ def running?
613
+ state == :running
614
+ end
615
+
616
+ # Returns true if the virtual machine state is powered off
617
+ #
618
+ # @return [Boolean] True if virtual machine state is powered off
619
+ def powered_off?
620
+ state == :powered_off
621
+ end
622
+
623
+ # Returns true if the virtual machine state is paused
624
+ #
625
+ # @return [Boolean] True if virtual machine state is paused
626
+ def paused?
627
+ state == :paused
628
+ end
629
+
630
+ # Returns true if the virtual machine state is saved
631
+ #
632
+ # @return [Boolean] True if virtual machine state is saved
633
+ def saved?
634
+ state == :saved
635
+ end
636
+
637
+ # Returns true if the virtual machine state is aborted
638
+ #
639
+ # @return [Boolean] True if virtual machine state is aborted
640
+ def aborted?
641
+ state == :aborted
642
+ end
643
+
644
+ # Loads the boot order for this virtual machine. This method should
645
+ # never be called directly. Instead, use the `boot_order` attribute
646
+ # to read and modify the boot order.
647
+ def get_boot_order(interface, key)
648
+ max_boot = Global.global.system_properties.max_boot_position
649
+
650
+ (1..max_boot).inject([]) do |order, position|
651
+ order << interface.get_boot_order(position)
652
+ order
653
+ end
654
+ end
655
+
656
+ # Sets the boot order for this virtual machine. This method should
657
+ # never be called directly. Instead, modify the `boot_order` array.
658
+ def set_boot_order(interface, key, value)
659
+ max_boot = Global.global.system_properties.max_boot_position
660
+ value = value.dup
661
+ value.concat(Array.new(max_boot - value.size)) if value.size < max_boot
662
+
663
+ (1..max_boot).each do |position|
664
+ interface.set_boot_order(position, value[position - 1])
665
+ end
666
+ end
667
+
668
+ def add_storage_controller(name, bus, type)
669
+ with_open_session do |session|
670
+ controller = session.machine.add_storage_controller(name, bus)
671
+ controller.controller_type = type
672
+ # Save the controller type
673
+ save_interface_attribute(:controller_type, controller)
674
+ end
675
+ end
676
+
677
+ def attach_storage(name, controller_port, device, device_type, storage_uuid)
678
+ with_open_session do |session|
679
+ session.machine.attach_device(name, controller_port, device,
680
+ device_type, storage_uuid)
681
+ end
682
+ end
683
+ end
684
+ end