virtualbox 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. data/.gitignore +2 -1
  2. data/Gemfile +1 -1
  3. data/Rakefile +1 -1
  4. data/Readme.md +5 -21
  5. data/VERSION +1 -1
  6. data/docs/WhatsNew.md +9 -47
  7. data/lib/virtualbox.rb +7 -30
  8. data/lib/virtualbox/abstract_model.rb +25 -5
  9. data/lib/virtualbox/abstract_model/attributable.rb +5 -1
  10. data/lib/virtualbox/abstract_model/dirty.rb +2 -0
  11. data/lib/virtualbox/abstract_model/interface_attributes.rb +96 -0
  12. data/lib/virtualbox/abstract_model/relatable.rb +19 -8
  13. data/lib/virtualbox/appliance.rb +59 -0
  14. data/lib/virtualbox/audio_adapter.rb +44 -0
  15. data/lib/virtualbox/bios.rb +44 -0
  16. data/lib/virtualbox/com.rb +23 -0
  17. data/lib/virtualbox/com/abstract_enum.rb +42 -0
  18. data/lib/virtualbox/com/abstract_implementer.rb +43 -0
  19. data/lib/virtualbox/com/abstract_interface.rb +165 -0
  20. data/lib/virtualbox/com/ffi/interface.rb +141 -0
  21. data/lib/virtualbox/com/ffi/interfaces.rb +42 -0
  22. data/lib/virtualbox/com/ffi/util.rb +101 -0
  23. data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
  24. data/lib/virtualbox/com/ffi_interface.rb +65 -0
  25. data/lib/virtualbox/com/implementer/base.rb +52 -0
  26. data/lib/virtualbox/com/implementer/ffi.rb +350 -0
  27. data/lib/virtualbox/com/implementer/mscom.rb +165 -0
  28. data/lib/virtualbox/com/implementer/nil.rb +10 -0
  29. data/lib/virtualbox/com/interface/appliance.rb +20 -0
  30. data/lib/virtualbox/com/interface/audio_adapter.rb +13 -0
  31. data/lib/virtualbox/com/interface/audio_controller_type.rb +9 -0
  32. data/lib/virtualbox/com/interface/audio_driver_type.rb +9 -0
  33. data/lib/virtualbox/com/interface/bios_boot_menu_mode.rb +9 -0
  34. data/lib/virtualbox/com/interface/bios_settings.rb +19 -0
  35. data/lib/virtualbox/com/interface/clipboard_mode.rb +9 -0
  36. data/lib/virtualbox/com/interface/console.rb +48 -0
  37. data/lib/virtualbox/com/interface/cpu_property_type.rb +9 -0
  38. data/lib/virtualbox/com/interface/device_type.rb +9 -0
  39. data/lib/virtualbox/com/interface/dhcp_server.rb +20 -0
  40. data/lib/virtualbox/com/interface/firmware_type.rb +9 -0
  41. data/lib/virtualbox/com/interface/guest_os_type.rb +21 -0
  42. data/lib/virtualbox/com/interface/host.rb +40 -0
  43. data/lib/virtualbox/com/interface/host_network_interface.rb +28 -0
  44. data/lib/virtualbox/com/interface/host_network_interface_medium_type.rb +9 -0
  45. data/lib/virtualbox/com/interface/host_network_interface_status.rb +9 -0
  46. data/lib/virtualbox/com/interface/host_network_interface_type.rb +9 -0
  47. data/lib/virtualbox/com/interface/host_usb_device.rb +11 -0
  48. data/lib/virtualbox/com/interface/host_usb_device_filter.rb +11 -0
  49. data/lib/virtualbox/com/interface/hw_virt_ex_property_type.rb +9 -0
  50. data/lib/virtualbox/com/interface/machine.rb +103 -0
  51. data/lib/virtualbox/com/interface/machine_state.rb +12 -0
  52. data/lib/virtualbox/com/interface/medium.rb +48 -0
  53. data/lib/virtualbox/com/interface/medium_attachment.rb +16 -0
  54. data/lib/virtualbox/com/interface/medium_format.rb +16 -0
  55. data/lib/virtualbox/com/interface/medium_state.rb +9 -0
  56. data/lib/virtualbox/com/interface/medium_type.rb +9 -0
  57. data/lib/virtualbox/com/interface/medium_variant.rb +9 -0
  58. data/lib/virtualbox/com/interface/network_adapter.rb +28 -0
  59. data/lib/virtualbox/com/interface/network_adapter_type.rb +9 -0
  60. data/lib/virtualbox/com/interface/network_attachment_type.rb +9 -0
  61. data/lib/virtualbox/com/interface/nsiexception.rb +21 -0
  62. data/lib/virtualbox/com/interface/nsisupports.rb +13 -0
  63. data/lib/virtualbox/com/interface/parallel_port.rb +15 -0
  64. data/lib/virtualbox/com/interface/port_mode.rb +9 -0
  65. data/lib/virtualbox/com/interface/progress.rb +58 -0
  66. data/lib/virtualbox/com/interface/serial_port.rb +17 -0
  67. data/lib/virtualbox/com/interface/session.rb +16 -0
  68. data/lib/virtualbox/com/interface/session_state.rb +9 -0
  69. data/lib/virtualbox/com/interface/session_type.rb +9 -0
  70. data/lib/virtualbox/com/interface/shared_folder.rb +15 -0
  71. data/lib/virtualbox/com/interface/snapshot.rb +18 -0
  72. data/lib/virtualbox/com/interface/storage_bus.rb +9 -0
  73. data/lib/virtualbox/com/interface/storage_controller.rb +21 -0
  74. data/lib/virtualbox/com/interface/storage_controller_type.rb +9 -0
  75. data/lib/virtualbox/com/interface/system_properties.rb +35 -0
  76. data/lib/virtualbox/com/interface/usb_controller.rb +18 -0
  77. data/lib/virtualbox/com/interface/usb_device.rb +22 -0
  78. data/lib/virtualbox/com/interface/usb_device_filter.rb +21 -0
  79. data/lib/virtualbox/com/interface/usb_device_filter_action.rb +9 -0
  80. data/lib/virtualbox/com/interface/usb_device_state.rb +9 -0
  81. data/lib/virtualbox/com/interface/virtual_box_error_info.rb +15 -0
  82. data/lib/virtualbox/com/interface/virtual_system_description.rb +17 -0
  83. data/lib/virtualbox/com/interface/virtual_system_description_type.rb +12 -0
  84. data/lib/virtualbox/com/interface/virtual_system_description_value_type.rb +9 -0
  85. data/lib/virtualbox/com/interface/virtualbox.rb +54 -0
  86. data/lib/virtualbox/com/interface/vrdp_auth_type.rb +9 -0
  87. data/lib/virtualbox/com/interface/vrdp_server.rb +17 -0
  88. data/lib/virtualbox/com/mscom_interface.rb +22 -0
  89. data/lib/virtualbox/com/util.rb +18 -0
  90. data/lib/virtualbox/dvd.rb +7 -94
  91. data/lib/virtualbox/exceptions.rb +24 -0
  92. data/lib/virtualbox/ext/glob_loader.rb +22 -0
  93. data/lib/virtualbox/ext/logger.rb +38 -0
  94. data/lib/virtualbox/ext/platform.rb +1 -1
  95. data/lib/virtualbox/extra_data.rb +25 -37
  96. data/lib/virtualbox/forwarded_port.rb +35 -13
  97. data/lib/virtualbox/global.rb +22 -80
  98. data/lib/virtualbox/hard_drive.rb +30 -97
  99. data/lib/virtualbox/lib.rb +82 -0
  100. data/lib/virtualbox/media.rb +7 -6
  101. data/lib/virtualbox/medium.rb +138 -0
  102. data/lib/virtualbox/medium_attachment.rb +61 -0
  103. data/lib/virtualbox/network_adapter.rb +134 -0
  104. data/lib/virtualbox/shared_folder.rb +53 -78
  105. data/lib/virtualbox/storage_controller.rb +76 -20
  106. data/lib/virtualbox/system_properties.rb +74 -0
  107. data/lib/virtualbox/usb_controller.rb +55 -0
  108. data/lib/virtualbox/version.rb +15 -0
  109. data/lib/virtualbox/virtual_system_description.rb +47 -0
  110. data/lib/virtualbox/vm.rb +160 -272
  111. data/test/test_helper.rb +0 -108
  112. data/test/virtualbox/abstract_model/attributable_test.rb +7 -1
  113. data/test/virtualbox/abstract_model/dirty_test.rb +1 -1
  114. data/test/virtualbox/abstract_model/interface_attributes_test.rb +169 -0
  115. data/test/virtualbox/abstract_model/relatable_test.rb +20 -0
  116. data/test/virtualbox/abstract_model_test.rb +40 -5
  117. data/test/virtualbox/appliance_test.rb +152 -0
  118. data/test/virtualbox/audio_adapter_test.rb +83 -0
  119. data/test/virtualbox/bios_test.rb +83 -0
  120. data/test/virtualbox/com/abstract_enum_test.rb +48 -0
  121. data/test/virtualbox/com/abstract_implementer_test.rb +39 -0
  122. data/test/virtualbox/com/abstract_interface_test.rb +139 -0
  123. data/test/virtualbox/com/ffi/interface_test.rb +249 -0
  124. data/test/virtualbox/com/ffi/util_test.rb +86 -0
  125. data/test/virtualbox/com/ffi_interface_test.rb +42 -0
  126. data/test/virtualbox/com/implementer/base_test.rb +37 -0
  127. data/test/virtualbox/com/implementer/ffi_test.rb +519 -0
  128. data/test/virtualbox/com/implementer/mscom_test.rb +208 -0
  129. data/test/virtualbox/com/mscom_interface_test.rb +17 -0
  130. data/test/virtualbox/com/util_test.rb +17 -0
  131. data/test/virtualbox/dvd_test.rb +4 -95
  132. data/test/virtualbox/ext/platform_test.rb +8 -0
  133. data/test/virtualbox/extra_data_test.rb +78 -102
  134. data/test/virtualbox/forwarded_port_test.rb +57 -7
  135. data/test/virtualbox/global_test.rb +25 -115
  136. data/test/virtualbox/hard_drive_test.rb +49 -212
  137. data/test/virtualbox/lib_test.rb +93 -0
  138. data/test/virtualbox/medium_attachment_test.rb +147 -0
  139. data/test/virtualbox/medium_test.rb +192 -0
  140. data/test/virtualbox/network_adapter_test.rb +160 -0
  141. data/test/virtualbox/shared_folder_test.rb +144 -160
  142. data/test/virtualbox/storage_controller_test.rb +166 -45
  143. data/test/virtualbox/system_properties_test.rb +87 -0
  144. data/test/virtualbox/usb_controller_test.rb +104 -0
  145. data/test/virtualbox/version_test.rb +34 -0
  146. data/test/virtualbox/virtual_system_description_test.rb +61 -0
  147. data/test/virtualbox/vm_test.rb +288 -322
  148. data/test/virtualbox_test.rb +1 -9
  149. data/virtualbox.gemspec +139 -23
  150. metadata +143 -27
  151. data/lib/virtualbox/attached_device.rb +0 -249
  152. data/lib/virtualbox/command.rb +0 -109
  153. data/lib/virtualbox/image.rb +0 -137
  154. data/lib/virtualbox/nic.rb +0 -111
  155. data/lib/virtualbox/system_property.rb +0 -55
  156. data/lib/virtualbox/usb.rb +0 -72
  157. data/test/virtualbox/attached_device_test.rb +0 -303
  158. data/test/virtualbox/command_test.rb +0 -152
  159. data/test/virtualbox/image_test.rb +0 -190
  160. data/test/virtualbox/nic_test.rb +0 -76
  161. data/test/virtualbox/system_property_test.rb +0 -71
  162. data/test/virtualbox/usb_test.rb +0 -35
@@ -5,22 +5,6 @@ module VirtualBox
5
5
  # allow the user to retrieve a list of all VMs, media, global extra data,
6
6
  # etc. Indeed, even methods like {VM.all} are implemented using this class.
7
7
  #
8
- # # Setting the Path to VirtualBox.xml
9
- #
10
- # **This is extremely important.**
11
- #
12
- # Much of the virtualbox gem requires a proper path to the global XML configuration
13
- # file for VirtualBox. This path is system and installation dependent. {Global}
14
- # does its best to guess the path by trying the default paths based on the
15
- # platform ruby is running on, but this is hardly foolproof. If you receive an
16
- # {Exceptions::ConfigurationException} at some point while running virtualbox,
17
- # you should use {Global.vboxconfig=} to set the path. An example is below:
18
- #
19
- # # Most installations won't need to do this, since the gem "guesses"
20
- # # the path based on OS, but if you need to set vboxconfig path
21
- # # explicitly:
22
- # VirtualBox::Global.vboxconfig = "~/.MyCustom/VirtualBox.xml"
23
- #
24
8
  # # Getting Global Data
25
9
  #
26
10
  # To retrieve the global data, use `Global.global`. This value is _cached_
@@ -46,19 +30,18 @@ module VirtualBox
46
30
  # relationships. The relationships are listed below. If you don't
47
31
  # understand this, read {Relatable}.
48
32
  #
49
- # relationship :vms, VM, :lazy => true
33
+ # relationship :vms, VM
50
34
  # relationship :media, Media
51
35
  # relationship :extra_data, ExtraData
36
+ # relationship :system_properties, :SystemProperties, :lazy => true
52
37
  #
53
38
  class Global < AbstractModel
54
- # The path to the global VirtualBox XML configuration file. This is
55
- # entirely system dependent and can be set with {vboxconfig=}. The default
56
- # is guessed based on the platform.
57
- @@vboxconfig = nil
39
+ attribute :lib, :readonly => true
58
40
 
59
- relationship :vms, VM, :lazy => true
60
- relationship :media, Media
61
- relationship :extra_data, ExtraData
41
+ relationship :vms, :VM, :lazy => true
42
+ relationship :media, :Media, :lazy => true
43
+ relationship :extra_data, :ExtraData, :lazy => true
44
+ relationship :system_properties, :SystemProperties, :lazy => true
62
45
 
63
46
  @@global_data = nil
64
47
 
@@ -71,73 +54,32 @@ module VirtualBox
71
54
  #
72
55
  # @param [Boolean] reload True if you want to force a reload of the data.
73
56
  # @return [Global]
74
- def global(reload = false)
75
- if !@@global_data || reload || reload?
76
- @@global_data = new(config)
77
- reloaded!
57
+ def global(reload=false)
58
+ if !@@global_data || reload
59
+ @@global_data = new(Lib.lib)
78
60
  end
79
61
 
80
62
  @@global_data
81
63
  end
82
64
 
83
- # Sets the path to the VirtualBox.xml file. This file should already
84
- # exist. VirtualBox itself manages this file, not this library.
85
- #
86
- # @param [String] Full path to the VirtualBox.xml file
87
- def vboxconfig=(value)
88
- @@vboxconfig = value
89
- end
90
-
91
- # Returns the path to the virtual box configuration file. If the path
92
- # has not yet been set, it attempts to infer it based on the
93
- # platform ruby is running on.
94
- def vboxconfig
95
- if @@vboxconfig.nil?
96
- if Platform.mac?
97
- @@vboxconfig = "~/Library/VirtualBox/VirtualBox.xml"
98
- elsif Platform.linux? || Platform.windows?
99
- @@vboxconfig = "~/.VirtualBox/VirtualBox.xml"
100
- else
101
- @@vboxconfig = "Unknown"
102
- end
103
- end
104
-
105
- File.expand_path(@@vboxconfig)
106
- end
107
-
108
- # Returns a boolean denoting whether or not the vboxconfig value is
109
- # valid or not.
110
- #
111
- # @return [Boolean]
112
- def vboxconfig?
113
- File.file?(vboxconfig)
114
- end
115
-
116
- # Returns the XML document of the configuration. This will raise an
117
- # {Exceptions::ConfigurationException} if the vboxconfig file doesn't
118
- # exist.
119
- #
120
- # @return [Nokogiri::XML::Document]
121
- def config
122
- raise Exceptions::ConfigurationException.new("The path to the global VirtualBox config must be set. See Global.vboxconfig=") unless vboxconfig?
123
- Command.parse_xml(vboxconfig)
124
- end
125
-
126
- # Expands path relative to the configuration file.
127
- #
128
- # @return [String]
129
- def expand_path(path)
130
- File.expand_path(path, File.dirname(vboxconfig))
65
+ # Resets the global data singleton. This is used for testing purposes.
66
+ def reset!
67
+ @@global_data = nil
131
68
  end
132
69
  end
133
70
 
134
- def initialize(document)
135
- @document = document
136
- populate_attributes(@document)
71
+ def initialize(lib)
72
+ write_attribute(:lib, lib)
73
+
74
+ # Required to load lazy relationships
75
+ existing_record!
137
76
  end
138
77
 
139
78
  def load_relationship(name)
140
- populate_relationship(:vms, @document)
79
+ populate_relationship(:vms, lib.virtualbox.machines)
80
+ populate_relationship(:media, lib)
81
+ populate_relationship(:extra_data, lib.virtualbox)
82
+ populate_relationship(:system_properties, lib.virtualbox.system_properties)
141
83
  end
142
84
  end
143
85
  end
@@ -70,15 +70,16 @@ module VirtualBox
70
70
  # listed below. If you aren't sure what this means or you can't understand
71
71
  # why the below is listed, please read {Attributable}.
72
72
  #
73
- # attribute :uuid, :readonly => true
74
- # attribute :location
75
- # attribute :accessible, :readonly => true
76
- # attribute :format, :default => "VDI"
77
- # attribute :size
78
- #
79
- class HardDrive < Image
80
- attribute :format, :default => "VDI"
81
- attribute :size, :lazy => true
73
+ # attribute :format, :default => "VDI", :property => :format
74
+ # attribute :logical_size, :property => :logical_size
75
+ # attribute :physical_size, :readonly => true, :property => :size
76
+ #
77
+ # There are more attributes on the {Medium} model, which {HardDrive} inherits
78
+ # from.
79
+ class HardDrive < Medium
80
+ attribute :format, :default => "VDI", :property => :format
81
+ attribute :logical_size, :property => :logical_size
82
+ attribute :physical_size, :readonly => true, :property => :size
82
83
 
83
84
  class <<self
84
85
  # Returns an array of all available hard drives as HardDrive
@@ -92,45 +93,15 @@ module VirtualBox
92
93
  # Finds one specific hard drive by UUID or file name. If the
93
94
  # hard drive can not be found, will return `nil`.
94
95
  #
95
- # @param [String] id The UUID or name of the hard drive
96
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
97
- # will be raised if the command failed.
96
+ # @param [String] id The UUID of the hard drive
98
97
  # @return [HardDrive]
99
98
  def find(id, raise_errors=false)
100
- raw = Command.vboxmanage("showhdinfo", id)
101
-
102
- data = raw.split(/\n\n/).collect { |v| parse_block(v) }.find { |v| !v.nil? }
103
-
104
- # Set equivalent fields
105
- data[:format] = data[:"storage format"]
106
- data[:size] = data[:"logical size"].split(/\s+/)[0] if data.has_key?(:"logical size")
107
-
108
- # Return new object
109
- new(data)
110
- rescue Exceptions::CommandFailedException
111
- raise if raise_errors
112
- nil
99
+ all.find { |hd| hd.uuid == id }
113
100
  end
114
101
 
115
- def populate_relationship(caller, doc)
116
- result = Proxies::Collection.new(caller)
117
-
118
- doc.css("MediaRegistry HardDisks HardDisk").each do |hd_node|
119
- data = {}
120
- hd_node.attributes.each do |key, value|
121
- data[key.downcase.to_sym] = value.to_s
122
- end
123
-
124
- # Strip the brackets off of UUID
125
- data[:uuid] = data[:uuid][1..-2]
126
-
127
- # Expand location relative to config location
128
- data[:location] = Global.expand_path(data[:location]) if data[:location]
129
-
130
- result << new(data)
131
- end
132
-
133
- result
102
+ # Override of {Medium.device_type}.
103
+ def device_type
104
+ :hard_disk
134
105
  end
135
106
  end
136
107
 
@@ -139,34 +110,27 @@ module VirtualBox
139
110
  # here. If no format is specified, the format of the source drive
140
111
  # will be used.
141
112
  #
142
- # @param [String] outputfile The output file. This should be just a
143
- # single filename, since VirtualBox will place it in the hard
144
- # drives folder.
113
+ # @param [String] outputfile The output file. This can be a full path
114
+ # or just a filename. If its just a filename, it will be placed in
115
+ # the default hard drives directory.
145
116
  # @param [String] format The format to convert to.
146
117
  # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
147
118
  # will be raised if the command failed.
148
119
  # @return [HardDrive] The new, cloned hard drive, or nil on failure.
149
- def clone(outputfile, format="VDI", raise_errors=false)
150
- raw = Command.vboxmanage("clonehd", uuid, outputfile, "--format", format, "--remember")
151
- return nil unless raw =~ /UUID: (.+?)$/
120
+ def clone(outputfile, format="VDI")
121
+ # Get main VirtualBox object
122
+ virtualbox = Lib.lib.virtualbox
152
123
 
153
- self.class.find($1.to_s)
154
- rescue Exceptions::CommandFailedException
155
- raise if raise_errors
156
- nil
157
- end
124
+ # Expand path relative to the default hard disk folder. This allows
125
+ # filenames to exist in the default folder while full paths will use
126
+ # the paths specified.
127
+ outputfile = File.expand_path(outputfile, virtualbox.system_properties.default_hard_disk_folder)
158
128
 
159
- # Override of {Image#image_type}.
160
- def image_type
161
- "hdd"
162
- end
163
-
164
- # Validates a hard drive.
165
- def validate
166
- super
129
+ # Create the new medium. This simply creates a new IMedium structure
130
+ new_medium = virtualbox.create_hard_disk(format, outputfile)
167
131
 
168
- validates_presence_of :format
169
- validates_presence_of :size
132
+ # Clone the current drive
133
+ interface.clone_to(new_medium, :standard, nil).wait_for_completion(-1)
170
134
  end
171
135
 
172
136
  # Creates a new hard drive.
@@ -182,14 +146,8 @@ module VirtualBox
182
146
  return false
183
147
  end
184
148
 
185
- raw = Command.vboxmanage("createhd", "--filename", location, "--size", size, "--format", read_attribute(:format), "--remember")
186
- return nil unless raw =~ /UUID: (.+?)$/
187
-
188
- # Just replace our attributes with the newly created ones. This also
189
- # will set new_record to false.
190
- populate_attributes(self.class.find($1.to_s).attributes)
149
+ # TODO
191
150
 
192
- # Return the success of the command
193
151
  true
194
152
  rescue Exceptions::CommandFailedException
195
153
  raise if raise_errors
@@ -214,30 +172,5 @@ module VirtualBox
214
172
  super
215
173
  end
216
174
  end
217
-
218
- # Destroys the hard drive. This deletes the hard drive off
219
- # of disk.
220
- #
221
- # **This operation is not reversable.**
222
- #
223
- # @param [Boolean] raise_errors If true, {Exceptions::CommandFailedException}
224
- # will be raised if the command failed.
225
- # @return [Boolean] True if command was successful, false otherwise.
226
- def destroy(raise_errors=false)
227
- Command.vboxmanage("closemedium", "disk", uuid, "--delete")
228
- true
229
- rescue Exceptions::CommandFailedException
230
- raise if raise_errors
231
- false
232
- end
233
-
234
- # Lazy load the lazy attributes for this model.
235
- def load_attribute(name)
236
- # Since the lazy attributes are related, we just load them all at once
237
- loaded_hd = self.class.find(uuid, true)
238
-
239
- write_attribute(:size, loaded_hd.size)
240
- write_attribute(:accessible, loaded_hd.accessible)
241
- end
242
175
  end
243
176
  end
@@ -0,0 +1,82 @@
1
+ module VirtualBox
2
+ # Used by the rest of the VirtualBox library to interface with
3
+ # the VirtualBox XPCOM library (VBoxXPCOMC). Most users will never need
4
+ # to interface with this class directly, except other to set the path to
5
+ # the `VBoxXPCOMC` lib.
6
+ #
7
+ # # Setting the Path to the VBoxXPCOMC Library
8
+ #
9
+ # This won't be necessary for 95% of users, and won't be necessary at all
10
+ # for windows users. But for unix users, the VirtualBox gem uses a dynamic
11
+ # library named `VBoxXPCOMC` to interface with VirtualBox. The gem does its
12
+ # best to guess the path to this gem based on the operating system ruby is
13
+ # running on, but in the case you get an error about it missing, you can
14
+ # easily set it:
15
+ #
16
+ # VirtualBox::Lib.lib_path = "/path/to/VBoxXPCOMC.so"
17
+ #
18
+ # **Windows users will never need to do this.**
19
+ #
20
+ class Lib
21
+ @@lib_path = nil
22
+ @@lib = nil
23
+
24
+ attr_reader :interface
25
+ attr_reader :virtualbox
26
+ attr_reader :session
27
+
28
+ class <<self
29
+ # Resets the initialized library (if there is any). This is primarily only
30
+ # used for testing.
31
+ def reset!
32
+ @@lib = nil
33
+ end
34
+
35
+ # The singleton instance of Lib.
36
+ #
37
+ # @return [Lib]
38
+ def lib
39
+ @@lib ||= new(lib_path)
40
+ end
41
+
42
+ # Sets the path to the VBoxXPCOMC library which is created with any
43
+ # VirtualBox install. 90% of the time, this won't have to be set manually,
44
+ # and instead the gem will try to find it for you.
45
+ #
46
+ # @param [String] Full path to the VBoxXPCOMC library
47
+ def lib_path=(value)
48
+ @@lib_path = value.nil? ? value : File.expand_path(value)
49
+ end
50
+
51
+ # Returns the path to the virtual box library. If the path
52
+ # has not yet been set, it attempts to infer it based on the
53
+ # platform ruby is running on.
54
+ def lib_path
55
+ if @@lib_path.nil?
56
+ if Platform.mac?
57
+ @@lib_path = ["/Applications/VirtualBox.app/Contents/MacOS/VBoxXPCOMC.dylib"]
58
+ elsif Platform.linux?
59
+ @@lib_path = ["/opt/VirtualBox/VBoxXPCOMC.so", "/usr/lib/virtualbox/VBoxXPCOMC.so"]
60
+ elsif Platform.windows?
61
+ @@lib_path = "Unknown"
62
+ else
63
+ @@lib_path = "Unknown"
64
+ end
65
+ end
66
+
67
+ @@lib_path
68
+ end
69
+ end
70
+
71
+ def initialize(lib_path)
72
+ if Platform.windows?
73
+ @interface = COM::MSCOMInterface.new
74
+ else
75
+ @interface = COM::FFIInterface.create(lib_path)
76
+ end
77
+
78
+ @virtualbox = @interface.virtualbox
79
+ @session = @interface.session
80
+ end
81
+ end
82
+ end
@@ -2,18 +2,19 @@ module VirtualBox
2
2
  # Represents the media registry within the global VirtualBox configuration.
3
3
  class Media < AbstractModel
4
4
  attribute :parent, :readonly => true
5
- relationship :hard_drives, HardDrive
6
- relationship :dvds, DVD
5
+ relationship :hard_drives, :HardDrive
6
+ relationship :dvds, :DVD
7
7
 
8
8
  class <<self
9
- def populate_relationship(caller, data)
10
- new(caller, data)
9
+ def populate_relationship(caller, lib)
10
+ new(caller, lib)
11
11
  end
12
12
  end
13
13
 
14
- def initialize(parent, document)
14
+ def initialize(parent, lib)
15
15
  populate_attributes({ :parent => parent }, :ignore_relationships => true)
16
- populate_relationships(document)
16
+ populate_relationship(:hard_drives, lib.virtualbox.hard_disks)
17
+ populate_relationship(:dvds, lib.virtualbox.dvd_images)
17
18
  end
18
19
  end
19
20
  end
@@ -0,0 +1,138 @@
1
+ module VirtualBox
2
+ # Represents a medium object part of VirtualBox. A medium is a
3
+ # hard drive, DVD, floppy disk, etc. Each of these share common
4
+ # properties represented here.
5
+ class Medium < AbstractModel
6
+ include SubclassListing
7
+
8
+ attribute :uuid, :readonly => :true, :property => :id
9
+ attribute :description, :readonly => true
10
+ attribute :location, :readonly => true
11
+ attribute :state, :readonly => true, :property => :refresh_state
12
+ attribute :interface, :readonly => true, :property => false
13
+
14
+ class <<self
15
+ # Populates a relationship with another model. Depending on the data sent
16
+ # through as the `media` parameter, this can either return a single value
17
+ # or an array of values. {Global}, for example, has a relationship of media,
18
+ # while a {MediumAttachment} has a relationship with a single medium.
19
+ #
20
+ # **This method typically won't be used except internally.**
21
+ def populate_relationship(caller, media)
22
+ if media.is_a?(Array)
23
+ # has many relationship
24
+ populate_array_relationship(caller, media)
25
+ else
26
+ # has one relationship
27
+ populate_single_relationship(caller, media)
28
+ end
29
+ end
30
+
31
+ # Populates a relationship which has many media.
32
+ #
33
+ # **This method typically won't be used except internally.**
34
+ #
35
+ # @return [Array<Medium>]
36
+ def populate_array_relationship(caller, media)
37
+ relation = Proxies::Collection.new(caller)
38
+
39
+ media.each do |medium|
40
+ # Skip media this class isn't interested in
41
+ next if device_type != :all && medium.device_type != device_type
42
+
43
+ # Wrap it up and add to the relationship
44
+ relation << new(medium)
45
+ end
46
+
47
+ relation
48
+ end
49
+
50
+ # Populates a relationship which has one medium. This method goes one step
51
+ # further and instantiates the proper class for the type of medium given.
52
+ # For example, given a `device_type` of `:hard_drive`, it would return a
53
+ # {HardDrive} object.
54
+ #
55
+ # **This method typically won't be used except internally.**
56
+ #
57
+ # @return [Medium]
58
+ def populate_single_relationship(caller, medium)
59
+ return nil if medium.nil?
60
+
61
+ subclasses.each do |subclass|
62
+ # Skip this class unless the device type matches
63
+ next unless subclass.device_type == medium.device_type
64
+
65
+ # Wrap it up and return it
66
+ return subclass.new(medium)
67
+ end
68
+
69
+ # If all else fails, just wrap it in a Medium
70
+ new(medium)
71
+ end
72
+
73
+ # Specifies the device type that a {Medium} class is interested in. This
74
+ # is `:all` on {Medium}, but is expected to be overridden by child classes.
75
+ # The value returned should be one of {COM::Interface::DeviceType}.
76
+ #
77
+ # @return [Symbol]
78
+ def device_type
79
+ :all
80
+ end
81
+ end
82
+
83
+ # Initializes a medium object, retrieving the attributes and information
84
+ # from the {COM::Interface::Medium} object given as the parameter. This initialization
85
+ # is done automatically by virtualbox when populating a relationship. Mediums should
86
+ # never be initialized manually.
87
+ #
88
+ # @param [COM::Interface::Medium] imedium
89
+ def initialize(imedium)
90
+ write_attribute(:interface, imedium)
91
+ initialize_attributes(imedium)
92
+ end
93
+
94
+ def initialize_attributes(imedium)
95
+ # First refresh the state (required for many attributes)
96
+ imedium.refresh_state
97
+
98
+ # Load interface attributes
99
+ load_interface_attributes(imedium)
100
+
101
+ # Clear dirtiness, since this should only be called initially and
102
+ # therefore shouldn't affect dirtiness
103
+ clear_dirty!
104
+
105
+ # But this is an existing record
106
+ existing_record!
107
+ end
108
+
109
+ # Returns the basename of the images location (the file name +extension)
110
+ #
111
+ # @return [String]
112
+ def filename
113
+ File.basename(location.to_s)
114
+ end
115
+
116
+ # Destroys the medium, optionally also phsyically destroying the backing
117
+ # storage. This removes this medium from the VirtualBox media registry.
118
+ # In order to remove the medium, it must not be attached to any virtual
119
+ # machine. If it is, an exception of some sort will be raised.
120
+ # This action happens *immediately* when the method is called, and is not
121
+ # deferred to a save.
122
+ def destroy(destroy_backing=false)
123
+ if destroy_backing
124
+ destroy_storage
125
+ else
126
+ interface.close
127
+ end
128
+ end
129
+
130
+ # Destroys the backing store of the medium and the media registry. This is
131
+ # analagous to calling {#destroy} with the first parameter set to true. This
132
+ # method requires that the medium not be attached to any virtual machine
133
+ # (running or not).
134
+ def destroy_storage
135
+ interface.delete_storage.wait_for_completion(-1)
136
+ end
137
+ end
138
+ end