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