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.
- data/.gitignore +2 -1
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/Readme.md +5 -21
- data/VERSION +1 -1
- data/docs/WhatsNew.md +9 -47
- data/lib/virtualbox.rb +7 -30
- data/lib/virtualbox/abstract_model.rb +25 -5
- data/lib/virtualbox/abstract_model/attributable.rb +5 -1
- data/lib/virtualbox/abstract_model/dirty.rb +2 -0
- data/lib/virtualbox/abstract_model/interface_attributes.rb +96 -0
- data/lib/virtualbox/abstract_model/relatable.rb +19 -8
- data/lib/virtualbox/appliance.rb +59 -0
- data/lib/virtualbox/audio_adapter.rb +44 -0
- data/lib/virtualbox/bios.rb +44 -0
- data/lib/virtualbox/com.rb +23 -0
- data/lib/virtualbox/com/abstract_enum.rb +42 -0
- data/lib/virtualbox/com/abstract_implementer.rb +43 -0
- data/lib/virtualbox/com/abstract_interface.rb +165 -0
- data/lib/virtualbox/com/ffi/interface.rb +141 -0
- data/lib/virtualbox/com/ffi/interfaces.rb +42 -0
- data/lib/virtualbox/com/ffi/util.rb +101 -0
- data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
- data/lib/virtualbox/com/ffi_interface.rb +65 -0
- data/lib/virtualbox/com/implementer/base.rb +52 -0
- data/lib/virtualbox/com/implementer/ffi.rb +350 -0
- data/lib/virtualbox/com/implementer/mscom.rb +165 -0
- data/lib/virtualbox/com/implementer/nil.rb +10 -0
- data/lib/virtualbox/com/interface/appliance.rb +20 -0
- data/lib/virtualbox/com/interface/audio_adapter.rb +13 -0
- data/lib/virtualbox/com/interface/audio_controller_type.rb +9 -0
- data/lib/virtualbox/com/interface/audio_driver_type.rb +9 -0
- data/lib/virtualbox/com/interface/bios_boot_menu_mode.rb +9 -0
- data/lib/virtualbox/com/interface/bios_settings.rb +19 -0
- data/lib/virtualbox/com/interface/clipboard_mode.rb +9 -0
- data/lib/virtualbox/com/interface/console.rb +48 -0
- data/lib/virtualbox/com/interface/cpu_property_type.rb +9 -0
- data/lib/virtualbox/com/interface/device_type.rb +9 -0
- data/lib/virtualbox/com/interface/dhcp_server.rb +20 -0
- data/lib/virtualbox/com/interface/firmware_type.rb +9 -0
- data/lib/virtualbox/com/interface/guest_os_type.rb +21 -0
- data/lib/virtualbox/com/interface/host.rb +40 -0
- data/lib/virtualbox/com/interface/host_network_interface.rb +28 -0
- data/lib/virtualbox/com/interface/host_network_interface_medium_type.rb +9 -0
- data/lib/virtualbox/com/interface/host_network_interface_status.rb +9 -0
- data/lib/virtualbox/com/interface/host_network_interface_type.rb +9 -0
- data/lib/virtualbox/com/interface/host_usb_device.rb +11 -0
- data/lib/virtualbox/com/interface/host_usb_device_filter.rb +11 -0
- data/lib/virtualbox/com/interface/hw_virt_ex_property_type.rb +9 -0
- data/lib/virtualbox/com/interface/machine.rb +103 -0
- data/lib/virtualbox/com/interface/machine_state.rb +12 -0
- data/lib/virtualbox/com/interface/medium.rb +48 -0
- data/lib/virtualbox/com/interface/medium_attachment.rb +16 -0
- data/lib/virtualbox/com/interface/medium_format.rb +16 -0
- data/lib/virtualbox/com/interface/medium_state.rb +9 -0
- data/lib/virtualbox/com/interface/medium_type.rb +9 -0
- data/lib/virtualbox/com/interface/medium_variant.rb +9 -0
- data/lib/virtualbox/com/interface/network_adapter.rb +28 -0
- data/lib/virtualbox/com/interface/network_adapter_type.rb +9 -0
- data/lib/virtualbox/com/interface/network_attachment_type.rb +9 -0
- data/lib/virtualbox/com/interface/nsiexception.rb +21 -0
- data/lib/virtualbox/com/interface/nsisupports.rb +13 -0
- data/lib/virtualbox/com/interface/parallel_port.rb +15 -0
- data/lib/virtualbox/com/interface/port_mode.rb +9 -0
- data/lib/virtualbox/com/interface/progress.rb +58 -0
- data/lib/virtualbox/com/interface/serial_port.rb +17 -0
- data/lib/virtualbox/com/interface/session.rb +16 -0
- data/lib/virtualbox/com/interface/session_state.rb +9 -0
- data/lib/virtualbox/com/interface/session_type.rb +9 -0
- data/lib/virtualbox/com/interface/shared_folder.rb +15 -0
- data/lib/virtualbox/com/interface/snapshot.rb +18 -0
- data/lib/virtualbox/com/interface/storage_bus.rb +9 -0
- data/lib/virtualbox/com/interface/storage_controller.rb +21 -0
- data/lib/virtualbox/com/interface/storage_controller_type.rb +9 -0
- data/lib/virtualbox/com/interface/system_properties.rb +35 -0
- data/lib/virtualbox/com/interface/usb_controller.rb +18 -0
- data/lib/virtualbox/com/interface/usb_device.rb +22 -0
- data/lib/virtualbox/com/interface/usb_device_filter.rb +21 -0
- data/lib/virtualbox/com/interface/usb_device_filter_action.rb +9 -0
- data/lib/virtualbox/com/interface/usb_device_state.rb +9 -0
- data/lib/virtualbox/com/interface/virtual_box_error_info.rb +15 -0
- data/lib/virtualbox/com/interface/virtual_system_description.rb +17 -0
- data/lib/virtualbox/com/interface/virtual_system_description_type.rb +12 -0
- data/lib/virtualbox/com/interface/virtual_system_description_value_type.rb +9 -0
- data/lib/virtualbox/com/interface/virtualbox.rb +54 -0
- data/lib/virtualbox/com/interface/vrdp_auth_type.rb +9 -0
- data/lib/virtualbox/com/interface/vrdp_server.rb +17 -0
- data/lib/virtualbox/com/mscom_interface.rb +22 -0
- data/lib/virtualbox/com/util.rb +18 -0
- data/lib/virtualbox/dvd.rb +7 -94
- data/lib/virtualbox/exceptions.rb +24 -0
- data/lib/virtualbox/ext/glob_loader.rb +22 -0
- data/lib/virtualbox/ext/logger.rb +38 -0
- data/lib/virtualbox/ext/platform.rb +1 -1
- data/lib/virtualbox/extra_data.rb +25 -37
- data/lib/virtualbox/forwarded_port.rb +35 -13
- data/lib/virtualbox/global.rb +22 -80
- data/lib/virtualbox/hard_drive.rb +30 -97
- data/lib/virtualbox/lib.rb +82 -0
- data/lib/virtualbox/media.rb +7 -6
- data/lib/virtualbox/medium.rb +138 -0
- data/lib/virtualbox/medium_attachment.rb +61 -0
- data/lib/virtualbox/network_adapter.rb +134 -0
- data/lib/virtualbox/shared_folder.rb +53 -78
- data/lib/virtualbox/storage_controller.rb +76 -20
- data/lib/virtualbox/system_properties.rb +74 -0
- data/lib/virtualbox/usb_controller.rb +55 -0
- data/lib/virtualbox/version.rb +15 -0
- data/lib/virtualbox/virtual_system_description.rb +47 -0
- data/lib/virtualbox/vm.rb +160 -272
- data/test/test_helper.rb +0 -108
- data/test/virtualbox/abstract_model/attributable_test.rb +7 -1
- data/test/virtualbox/abstract_model/dirty_test.rb +1 -1
- data/test/virtualbox/abstract_model/interface_attributes_test.rb +169 -0
- data/test/virtualbox/abstract_model/relatable_test.rb +20 -0
- data/test/virtualbox/abstract_model_test.rb +40 -5
- data/test/virtualbox/appliance_test.rb +152 -0
- data/test/virtualbox/audio_adapter_test.rb +83 -0
- data/test/virtualbox/bios_test.rb +83 -0
- data/test/virtualbox/com/abstract_enum_test.rb +48 -0
- data/test/virtualbox/com/abstract_implementer_test.rb +39 -0
- data/test/virtualbox/com/abstract_interface_test.rb +139 -0
- data/test/virtualbox/com/ffi/interface_test.rb +249 -0
- data/test/virtualbox/com/ffi/util_test.rb +86 -0
- data/test/virtualbox/com/ffi_interface_test.rb +42 -0
- data/test/virtualbox/com/implementer/base_test.rb +37 -0
- data/test/virtualbox/com/implementer/ffi_test.rb +519 -0
- data/test/virtualbox/com/implementer/mscom_test.rb +208 -0
- data/test/virtualbox/com/mscom_interface_test.rb +17 -0
- data/test/virtualbox/com/util_test.rb +17 -0
- data/test/virtualbox/dvd_test.rb +4 -95
- data/test/virtualbox/ext/platform_test.rb +8 -0
- data/test/virtualbox/extra_data_test.rb +78 -102
- data/test/virtualbox/forwarded_port_test.rb +57 -7
- data/test/virtualbox/global_test.rb +25 -115
- data/test/virtualbox/hard_drive_test.rb +49 -212
- data/test/virtualbox/lib_test.rb +93 -0
- data/test/virtualbox/medium_attachment_test.rb +147 -0
- data/test/virtualbox/medium_test.rb +192 -0
- data/test/virtualbox/network_adapter_test.rb +160 -0
- data/test/virtualbox/shared_folder_test.rb +144 -160
- data/test/virtualbox/storage_controller_test.rb +166 -45
- data/test/virtualbox/system_properties_test.rb +87 -0
- data/test/virtualbox/usb_controller_test.rb +104 -0
- data/test/virtualbox/version_test.rb +34 -0
- data/test/virtualbox/virtual_system_description_test.rb +61 -0
- data/test/virtualbox/vm_test.rb +288 -322
- data/test/virtualbox_test.rb +1 -9
- data/virtualbox.gemspec +139 -23
- metadata +143 -27
- data/lib/virtualbox/attached_device.rb +0 -249
- data/lib/virtualbox/command.rb +0 -109
- data/lib/virtualbox/image.rb +0 -137
- data/lib/virtualbox/nic.rb +0 -111
- data/lib/virtualbox/system_property.rb +0 -55
- data/lib/virtualbox/usb.rb +0 -72
- data/test/virtualbox/attached_device_test.rb +0 -303
- data/test/virtualbox/command_test.rb +0 -152
- data/test/virtualbox/image_test.rb +0 -190
- data/test/virtualbox/nic_test.rb +0 -76
- data/test/virtualbox/system_property_test.rb +0 -71
- data/test/virtualbox/usb_test.rb +0 -35
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/Readme.md
CHANGED
|
@@ -11,10 +11,9 @@ Windows, Linux, and OS X. After installation, install the gem:
|
|
|
11
11
|
|
|
12
12
|
sudo gem install virtualbox
|
|
13
13
|
|
|
14
|
-
The gem
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
VirtualBox::Command.vboxmanage = "/path/to/my/VBoxManage"
|
|
14
|
+
The gem uses the native COM interface with VirtualBox provides to communicate with
|
|
15
|
+
VirtualBox. On Windows, this is globally available. On Linux-based machines, the gem
|
|
16
|
+
uses Ruby-FFI to talk to a dynamic library. No configuration should be necessary.
|
|
18
17
|
|
|
19
18
|
## Basic Usage
|
|
20
19
|
|
|
@@ -33,30 +32,15 @@ Below are some examples:
|
|
|
33
32
|
vm = VirtualBox::VM.find("my-vm")
|
|
34
33
|
|
|
35
34
|
# Let's first print out some basic info about the VM
|
|
36
|
-
puts "Memory: #{vm.
|
|
37
|
-
|
|
38
|
-
vm.storage_controllers.each do |sc|
|
|
39
|
-
sc.attached_devices.each do |device|
|
|
40
|
-
puts "Attached Device: #{device.uuid}"
|
|
41
|
-
end
|
|
42
|
-
end
|
|
35
|
+
puts "Memory: #{vm.memory_size}"
|
|
43
36
|
|
|
44
37
|
# Let's modify the memory and name...
|
|
45
|
-
vm.
|
|
38
|
+
vm.memory_size = 360
|
|
46
39
|
vm.name = "my-renamed-vm"
|
|
47
40
|
|
|
48
41
|
# Save it!
|
|
49
42
|
vm.save
|
|
50
43
|
|
|
51
|
-
Or here is an example of creating a hard drive:
|
|
52
|
-
|
|
53
|
-
require 'virtualbox'
|
|
54
|
-
|
|
55
|
-
hd = VirtualBox::HardDrive.new
|
|
56
|
-
hd.location = "foo.vdi"
|
|
57
|
-
hd.size = 2000 # megabytes
|
|
58
|
-
hd.save
|
|
59
|
-
|
|
60
44
|
## Known Issues or Uncompleted Features
|
|
61
45
|
|
|
62
46
|
VirtualBox has a _ton_ of features! As such, this gem is still not totally complete.
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.6.0
|
data/docs/WhatsNew.md
CHANGED
|
@@ -1,50 +1,12 @@
|
|
|
1
|
-
# What's New in 0.
|
|
1
|
+
# What's New in 0.6.x?
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Native Interface
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
The VirtualBox gem no longer piggy-backs on top of `VBoxManage` or XML configuration files.
|
|
6
|
+
The gem now uses the native interface provided by VirtualBox to communicate. The result of
|
|
7
|
+
this is a _huge_ speed increase which simply would not have been possible otherwise, and
|
|
8
|
+
stability across versions. In addition to that, the entire VirtualBox API is now at your
|
|
9
|
+
disposal. While the gem itself doesn't yet support creating VMs and so on, the API is available
|
|
10
|
+
for you to do it manually (if you really wanted to!).
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
XML. The virtualbox library will do its best to guess this path based on the operating
|
|
12
|
-
system, but this is hardly foolproof. To set the virtualbox config path, it is a simple
|
|
13
|
-
one-liner:
|
|
14
|
-
|
|
15
|
-
# Remember, this won't be necessary MOST of the time
|
|
16
|
-
VirtualBox::Global.vboxconfig = "~/path/to/VirtualBox.xml"
|
|
17
|
-
|
|
18
|
-
## Lazy Loading of Attributes and Relationships
|
|
19
|
-
|
|
20
|
-
Although still not widely used (will be in future patch releases), some attributes and
|
|
21
|
-
relationships are now _lazy loaded_. This means that since they're probably expensive
|
|
22
|
-
to load (many system calls, heavy parsing, etc.) they aren't loaded initially. Instead,
|
|
23
|
-
they are only loaded if they're used. This means that you don't incur the penalty cost
|
|
24
|
-
of loading them unless you use it! Fantastic!
|
|
25
|
-
|
|
26
|
-
There is no real "example code" for this feature since to the casual user, it happens
|
|
27
|
-
transparently in the background and generally "just works." If you're _really_ curious,
|
|
28
|
-
then feel free to check out any class which derives from {VirtualBox::AbstractModel}
|
|
29
|
-
and any attribute or relationship with the `:lazy => true` option is lazy loaded!
|
|
30
|
-
|
|
31
|
-
## System Properties
|
|
32
|
-
|
|
33
|
-
A small but meaningful update is the ability to view the system properties for the
|
|
34
|
-
host system which VirtualBox is running. This is done via the {VirtualBox::SystemProperty}
|
|
35
|
-
class, which is simply a `Hash`. System properties are immutable properties defined
|
|
36
|
-
by the host system, which typically are limits imposed upon VirtualBox, such as
|
|
37
|
-
maximum RAM size or default path to machine files. Retrieving the system properties
|
|
38
|
-
is quite easy:
|
|
39
|
-
|
|
40
|
-
properties = VirtualBox::SystemProperty.all
|
|
41
|
-
properties.each do |key, value|
|
|
42
|
-
puts "#{key} = #{value}"
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
## USB Device Relationship on VMs
|
|
46
|
-
|
|
47
|
-
Previously, {VirtualBox::VM VM} object would only be able to tell you if there
|
|
48
|
-
were USB devices enabled or not. Now, `usbs` is a full-fledged relationship
|
|
49
|
-
on VM. This relationship is access just like any other. For more information
|
|
50
|
-
view the {VirtualBox::USB USB} class.
|
|
12
|
+
Future versions will support more and more of the API.
|
data/lib/virtualbox.rb
CHANGED
|
@@ -1,34 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
# Load the glob loader, which will handle the loading of all the other files
|
|
2
|
+
libdir = File.join(File.dirname(__FILE__), "virtualbox")
|
|
3
|
+
require File.expand_path("ext/glob_loader", libdir)
|
|
2
4
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
# Internal Dependencies
|
|
7
|
-
require 'virtualbox/ext/platform'
|
|
8
|
-
require 'virtualbox/exceptions'
|
|
9
|
-
require 'virtualbox/command'
|
|
10
|
-
require 'virtualbox/abstract_model'
|
|
11
|
-
require 'virtualbox/proxies/collection'
|
|
12
|
-
require 'virtualbox/image'
|
|
13
|
-
require 'virtualbox/attached_device'
|
|
14
|
-
require 'virtualbox/dvd'
|
|
15
|
-
require 'virtualbox/extra_data'
|
|
16
|
-
require 'virtualbox/forwarded_port'
|
|
17
|
-
require 'virtualbox/hard_drive'
|
|
18
|
-
require 'virtualbox/nic'
|
|
19
|
-
require 'virtualbox/usb'
|
|
20
|
-
require 'virtualbox/shared_folder'
|
|
21
|
-
require 'virtualbox/storage_controller'
|
|
22
|
-
require 'virtualbox/vm'
|
|
23
|
-
require 'virtualbox/media'
|
|
24
|
-
require 'virtualbox/global'
|
|
25
|
-
require 'virtualbox/system_property'
|
|
5
|
+
# Load them up
|
|
6
|
+
VirtualBox::GlobLoader.glob_require(libdir, %w{ext/logger ext/platform ext/subclass_listing com abstract_model medium})
|
|
26
7
|
|
|
8
|
+
# Setup the top-level module methods
|
|
27
9
|
module VirtualBox
|
|
28
|
-
|
|
29
|
-
# Returns installed VirtualBox version like '3.1.2r56127'.
|
|
30
|
-
def version
|
|
31
|
-
Command.vboxmanage("-v").chomp.strip
|
|
32
|
-
end
|
|
33
|
-
end
|
|
10
|
+
extend Version
|
|
34
11
|
end
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
['abstract_model/attributable',
|
|
2
|
+
'abstract_model/interface_attributes',
|
|
3
|
+
'abstract_model/dirty',
|
|
4
|
+
'abstract_model/relatable',
|
|
5
|
+
'abstract_model/validatable'].each do |lib|
|
|
6
|
+
require File.expand_path(lib, File.dirname(__FILE__))
|
|
7
|
+
end
|
|
5
8
|
|
|
6
9
|
module VirtualBox
|
|
7
10
|
# AbstractModel is the base class used for most of virtualbox's classes.
|
|
@@ -9,7 +12,10 @@ module VirtualBox
|
|
|
9
12
|
#
|
|
10
13
|
# @abstract
|
|
11
14
|
class AbstractModel
|
|
15
|
+
include Logger
|
|
16
|
+
|
|
12
17
|
include Attributable
|
|
18
|
+
include InterfaceAttributes
|
|
13
19
|
include Dirty
|
|
14
20
|
include Relatable
|
|
15
21
|
include Validatable
|
|
@@ -122,6 +128,20 @@ module VirtualBox
|
|
|
122
128
|
clear_dirty!(key)
|
|
123
129
|
end
|
|
124
130
|
|
|
131
|
+
# Saves only changed interface attributes.
|
|
132
|
+
def save_changed_interface_attributes(interface)
|
|
133
|
+
changes.each do |key, values|
|
|
134
|
+
save_interface_attribute(key, interface)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Overrides {InterfaceAttributes.save_interface_attribute} to clear the
|
|
139
|
+
# dirty state of the attribute.
|
|
140
|
+
def save_interface_attribute(key, interface)
|
|
141
|
+
super
|
|
142
|
+
clear_dirty!(key)
|
|
143
|
+
end
|
|
144
|
+
|
|
125
145
|
# Overriding {Attributable#lazy_attribute?} to always return false for
|
|
126
146
|
# new records, since new records shouldn't load lazy data.
|
|
127
147
|
def lazy_attribute?(*args)
|
|
@@ -217,7 +237,7 @@ module VirtualBox
|
|
|
217
237
|
|
|
218
238
|
self.class.attributes.each do |name, options|
|
|
219
239
|
value = read_attribute(name)
|
|
220
|
-
value = if value.is_a?(AbstractModel)
|
|
240
|
+
value = if value.is_a?(AbstractModel) || value.is_a?(COM::AbstractInterface)
|
|
221
241
|
"#<#{value.class.name}>"
|
|
222
242
|
else
|
|
223
243
|
value.inspect
|
|
@@ -214,7 +214,11 @@ module VirtualBox
|
|
|
214
214
|
load_attribute(name.to_sym)
|
|
215
215
|
end
|
|
216
216
|
|
|
217
|
-
attributes[name]
|
|
217
|
+
if attributes[name].nil?
|
|
218
|
+
self.class.attributes[name][:default]
|
|
219
|
+
else
|
|
220
|
+
attributes[name]
|
|
221
|
+
end
|
|
218
222
|
end
|
|
219
223
|
end
|
|
220
224
|
|
|
@@ -93,6 +93,8 @@ module VirtualBox
|
|
|
93
93
|
# @param [Object] value The new value being set
|
|
94
94
|
def set_dirty!(name, current, value)
|
|
95
95
|
if current != value
|
|
96
|
+
name = name.to_sym
|
|
97
|
+
|
|
96
98
|
# If its the first time this attribute has changed, store the
|
|
97
99
|
# original value in the first field
|
|
98
100
|
changes[name] ||= [current, nil]
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module VirtualBox
|
|
2
|
+
class AbstractModel
|
|
3
|
+
# Module which can be included which defines helper methods to DRY out the
|
|
4
|
+
# code which handles attributes with {VirtualBox::COM} interfaces. This
|
|
5
|
+
# module works _alongside_ the {Attributable} module, so **both are required**.
|
|
6
|
+
module InterfaceAttributes
|
|
7
|
+
# Loads the attributes which have an interface getter and writes
|
|
8
|
+
# their values.
|
|
9
|
+
#
|
|
10
|
+
# @param [VirtualBox::COM::Interface] interface
|
|
11
|
+
def load_interface_attributes(interface)
|
|
12
|
+
self.class.attributes.each do |key, options|
|
|
13
|
+
load_interface_attribute(key, interface)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Loads a single interface attribute.
|
|
18
|
+
#
|
|
19
|
+
# @param [Symbol] key The attribute to load
|
|
20
|
+
# @param [VirtualBox::COM::Interface] interface The interface
|
|
21
|
+
def load_interface_attribute(key, interface)
|
|
22
|
+
# Return unless we have a valid interface attribute with a getter
|
|
23
|
+
return unless has_attribute?(key)
|
|
24
|
+
options = self.class.attributes[key.to_sym]
|
|
25
|
+
return if options.has_key?(:property) && !options[:property]
|
|
26
|
+
getter = options[:property] || options[:property_getter] || key.to_sym
|
|
27
|
+
return unless getter
|
|
28
|
+
|
|
29
|
+
# Convert the getter to a proc and call it
|
|
30
|
+
getter = spec_to_proc(getter)
|
|
31
|
+
write_attribute(key, getter.call(interface))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Saves all the attributes which have an interface setter.
|
|
35
|
+
def save_interface_attributes(interface)
|
|
36
|
+
self.class.attributes.each do |key, options|
|
|
37
|
+
save_interface_attribute(key, interface)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Saves a single interface attribute
|
|
42
|
+
#
|
|
43
|
+
# @param [Symbol] key The attribute to write
|
|
44
|
+
# @param [VirtualBox::COM::Interface] interface The interface
|
|
45
|
+
# @param [Object] value The value to write
|
|
46
|
+
def save_interface_attribute(key, interface)
|
|
47
|
+
# Return unless we have a valid interface attribute with a setter
|
|
48
|
+
return unless has_attribute?(key)
|
|
49
|
+
options = self.class.attributes[key.to_sym]
|
|
50
|
+
return if options[:readonly]
|
|
51
|
+
return if options.has_key?(:property) && !options[:property]
|
|
52
|
+
|
|
53
|
+
setter = options[:property] || options[:property_setter] || "#{key}=".to_sym
|
|
54
|
+
return unless setter
|
|
55
|
+
|
|
56
|
+
# Convert the setter to a proc and call it
|
|
57
|
+
setter = spec_to_proc(setter)
|
|
58
|
+
setter.call(interface, read_attribute(key))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Converts a getter/setter specification to a Proc which can be called
|
|
62
|
+
# to obtain or set a value. There are multiple ways to specify the getter
|
|
63
|
+
# and/or setter of an interface attribute:
|
|
64
|
+
#
|
|
65
|
+
# ## Symbol
|
|
66
|
+
#
|
|
67
|
+
# A symbol represents a method to call on the interface. An example of the
|
|
68
|
+
# declaration and resulting method call are shown below:
|
|
69
|
+
#
|
|
70
|
+
# attribute :foo, :property_getter => :get_foo
|
|
71
|
+
#
|
|
72
|
+
# Converts to:
|
|
73
|
+
#
|
|
74
|
+
# interface.get_foo
|
|
75
|
+
#
|
|
76
|
+
# ## Proc
|
|
77
|
+
#
|
|
78
|
+
# A proc is called with the interface and it is expected to return the value
|
|
79
|
+
# for a getter. For a setter, the interface and the value is sent in as
|
|
80
|
+
# parameters to the Proc.
|
|
81
|
+
#
|
|
82
|
+
# attribute :foo, :property_getter => Proc.new { |i| i.get_foo }
|
|
83
|
+
#
|
|
84
|
+
def spec_to_proc(spec)
|
|
85
|
+
# Return the spec as-is if its a proc
|
|
86
|
+
return spec if spec.is_a?(Proc)
|
|
87
|
+
|
|
88
|
+
if spec.is_a?(Symbol)
|
|
89
|
+
# For symbols, wrap up a method send in a Proc and return
|
|
90
|
+
# that
|
|
91
|
+
return Proc.new { |m, *args| m.send(spec, *args) }
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -209,8 +209,8 @@ module VirtualBox
|
|
|
209
209
|
# calls `save_relationship` on the relationship class.
|
|
210
210
|
def save_relationship(name, *args)
|
|
211
211
|
options = self.class.relationships_hash[name]
|
|
212
|
-
return unless
|
|
213
|
-
|
|
212
|
+
return unless relationship_class(name).respond_to?(:save_relationship)
|
|
213
|
+
relationship_class(name).save_relationship(self, relationship_data[name], *args)
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
# The equivalent to {Attributable#populate_attributes}, but with
|
|
@@ -224,8 +224,8 @@ module VirtualBox
|
|
|
224
224
|
# Populate a single relationship.
|
|
225
225
|
def populate_relationship(name, data)
|
|
226
226
|
options = self.class.relationships_hash[name]
|
|
227
|
-
return unless
|
|
228
|
-
relationship_data[name] =
|
|
227
|
+
return unless relationship_class(name).respond_to?(:populate_relationship)
|
|
228
|
+
relationship_data[name] = relationship_class(name).populate_relationship(self, data)
|
|
229
229
|
end
|
|
230
230
|
|
|
231
231
|
# Calls `destroy_relationship` on each of the relationships. Any
|
|
@@ -244,13 +244,13 @@ module VirtualBox
|
|
|
244
244
|
# @param [Symbol] name The name of the relationship
|
|
245
245
|
def destroy_relationship(name, *args)
|
|
246
246
|
options = self.class.relationships_hash[name]
|
|
247
|
-
return unless options &&
|
|
247
|
+
return unless options && relationship_class(name).respond_to?(:destroy_relationship)
|
|
248
248
|
|
|
249
249
|
# Read relationship, which forces lazy relationships to load, which is
|
|
250
250
|
# probably necessary for destroying
|
|
251
251
|
read_relationship(name)
|
|
252
252
|
|
|
253
|
-
|
|
253
|
+
relationship_class(name).destroy_relationship(self, relationship_data[name], *args)
|
|
254
254
|
end
|
|
255
255
|
|
|
256
256
|
# Hash to data associated with relationships. You should instead
|
|
@@ -281,6 +281,17 @@ module VirtualBox
|
|
|
281
281
|
relationship_data.has_key?(key)
|
|
282
282
|
end
|
|
283
283
|
|
|
284
|
+
# Returns the class for a given relationship. This method handles converting
|
|
285
|
+
# a string/symbol into the proper class.
|
|
286
|
+
#
|
|
287
|
+
# @return [Class]
|
|
288
|
+
def relationship_class(key)
|
|
289
|
+
options = self.class.relationships_hash[key.to_sym]
|
|
290
|
+
klass = options[:klass]
|
|
291
|
+
klass = Object.module_eval("#{klass}") unless klass.is_a?(Class)
|
|
292
|
+
klass
|
|
293
|
+
end
|
|
294
|
+
|
|
284
295
|
# Sets a relationship to the given value. This is not guaranteed to
|
|
285
296
|
# do anything, since "set_relationship" will be called on the class
|
|
286
297
|
# that the relationship is associated with and its expected to return
|
|
@@ -299,8 +310,8 @@ module VirtualBox
|
|
|
299
310
|
relationship = self.class.relationships_hash[key]
|
|
300
311
|
return unless relationship
|
|
301
312
|
|
|
302
|
-
raise Exceptions::NonSettableRelationshipException.new unless
|
|
303
|
-
relationship_data[key] =
|
|
313
|
+
raise Exceptions::NonSettableRelationshipException.new unless relationship_class(key).respond_to?(:set_relationship)
|
|
314
|
+
relationship_data[key] = relationship_class(key).set_relationship(self, relationship_data[key], value)
|
|
304
315
|
end
|
|
305
316
|
end
|
|
306
317
|
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module VirtualBox
|
|
2
|
+
# Represents an VirtualBox "appliance" which is an exported virtual machine or
|
|
3
|
+
# virtual machines. Appliances typically come with an OVF file and one or more
|
|
4
|
+
# compressed hard disks, and can be used to import directly into other VirtualBox
|
|
5
|
+
# installations. Appliances allow for virtual machine portability.
|
|
6
|
+
class Appliance < AbstractModel
|
|
7
|
+
attribute :path
|
|
8
|
+
attribute :interface, :readonly => true, :property => false
|
|
9
|
+
relationship :virtual_systems, :VirtualSystemDescription
|
|
10
|
+
|
|
11
|
+
def initialize(*args)
|
|
12
|
+
write_attribute(:interface, Lib.lib.virtualbox.create_appliance)
|
|
13
|
+
|
|
14
|
+
initialize_from_path(*args) if args.length == 1
|
|
15
|
+
|
|
16
|
+
clear_dirty!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Initializes this Appliance instance from a path to an OVF file. This sets
|
|
20
|
+
# up the relationships and so on.
|
|
21
|
+
#
|
|
22
|
+
# @param [String] path Path to the OVF file.
|
|
23
|
+
def initialize_from_path(path)
|
|
24
|
+
# Read in the data from the path
|
|
25
|
+
interface.read(path).wait_for_completion(-1)
|
|
26
|
+
|
|
27
|
+
# Interpret the data to fill in the interface properties
|
|
28
|
+
interface.interpret
|
|
29
|
+
|
|
30
|
+
# Load the interface attributes
|
|
31
|
+
load_interface_attributes(interface)
|
|
32
|
+
|
|
33
|
+
# Fill in the virtual systems
|
|
34
|
+
populate_relationship(:virtual_systems, interface.virtual_system_descriptions)
|
|
35
|
+
|
|
36
|
+
# Should be an existing record
|
|
37
|
+
existing_record!
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Imports the machines associated with this appliance. If a block is given,
|
|
41
|
+
# it will be yielded every percent that the operation progresses. This can be
|
|
42
|
+
# done to check the progress of the import.
|
|
43
|
+
def import(&block)
|
|
44
|
+
interface.import_machines.wait(&block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Exports the machines to the given path. If a block is given, it will be yielded
|
|
48
|
+
# every percent that the operation progresses. This can be done to check the progress
|
|
49
|
+
# of the export in real-time.
|
|
50
|
+
def export(&block)
|
|
51
|
+
interface.write("ovf-1.0", path).wait(&block)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Adds a VM to the appliance
|
|
55
|
+
def add_machine(vm)
|
|
56
|
+
vm.interface.export(interface)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|