bbrowning-virtualbox 0.7.6.dev

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