virtualbox-com 0.9.6
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 +8 -0
- data/Gemfile +9 -0
- data/LICENSE +19 -0
- data/Rakefile +8 -0
- data/Readme.md +59 -0
- data/examples/simple.rb +43 -0
- data/lib/virtualbox-com.rb +1 -0
- data/lib/virtualbox/com.rb +51 -0
- data/lib/virtualbox/com/abstract_enum.rb +51 -0
- data/lib/virtualbox/com/abstract_interface.rb +144 -0
- data/lib/virtualbox/com/abstract_model.rb +14 -0
- data/lib/virtualbox/com/exceptions.rb +32 -0
- data/lib/virtualbox/com/iid.rb +43 -0
- data/lib/virtualbox/com/model/4.2-gen.rb +2720 -0
- data/lib/virtualbox/com/model/4.2.rb +97 -0
- data/lib/virtualbox/com/util.rb +119 -0
- data/lib/virtualbox/com/version.rb +5 -0
- data/lib/virtualbox/com/xpcomc-ffi.rb +76 -0
- data/lib/virtualbox/com/xpcomc-ffi/binding.rb +87 -0
- data/lib/virtualbox/com/xpcomc-ffi/implementer.rb +86 -0
- data/lib/virtualbox/com/xpcomc-ffi/lib.rb +90 -0
- data/lib/virtualbox/com/xpcomc-ffi/model-types.rb +15 -0
- data/lib/virtualbox/com/xpcomc-ffi/sig.rb +342 -0
- data/lib/virtualbox/com/xpcomc-ffi/spec.rb +58 -0
- data/lib/virtualbox/com/xpcomc-ffi/xpcomc-vbox.rb +54 -0
- data/scripts/xidl-conv.rb +124 -0
- data/virtualbox-com.gemspec +27 -0
- metadata +123 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Mitchell Hashimoto.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/Rakefile
ADDED
data/Readme.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# VirtualBox-Com Ruby Gem
|
2
|
+
|
3
|
+
This is a simplified version of the unmaintained virtualbox gem
|
4
|
+
by [Mitchell Hashimoto](https://github.com/mitchellh)
|
5
|
+
|
6
|
+
The VirtualBox::COM ruby gem is a library which allows anyone to control
|
7
|
+
VirtualBox from ruby code! Create, destroy, start, stop, suspend, and
|
8
|
+
resume virtual machines. Also list virtual machines, list hard
|
9
|
+
drives, network devices, etc.
|
10
|
+
|
11
|
+
## Installation and Requirements
|
12
|
+
|
13
|
+
First you need to install [VirtualBox](http://www.virtualbox.org/)
|
14
|
+
which is available for Windows, Linux, and OS X. After installation,
|
15
|
+
install the gem:
|
16
|
+
|
17
|
+
sudo gem install virtualbox-com
|
18
|
+
|
19
|
+
The gem uses the native COM interface with VirtualBox provides to
|
20
|
+
communicate with VirtualBox. The gem uses Ruby-FFI to talk to a
|
21
|
+
dynamic library. No configuration should be necessary.
|
22
|
+
|
23
|
+
## Basic Usage
|
24
|
+
|
25
|
+
require 'virtualbox-com'
|
26
|
+
|
27
|
+
lib = VirtualBox::COM
|
28
|
+
|
29
|
+
puts lib.virtualbox.machines[0].name
|
30
|
+
puts lib.virtualbox.find_machine('Windows').groups
|
31
|
+
|
32
|
+
## Known Issues or Uncompleted Features
|
33
|
+
|
34
|
+
All the classes are generated from the VirtualBox.xidl
|
35
|
+
|
36
|
+
## Reporting Bugs or Feature Requests
|
37
|
+
|
38
|
+
Please use the [issue tracker](https://github.com/sdalu/virtualbox-com/issues).
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
If you'd like to contribute to VirtualBox, the first step to developing is to
|
43
|
+
clone this repo, get [bundler](http://github.com/carlhuda/bundler) if you
|
44
|
+
don't have it already, and do the following:
|
45
|
+
|
46
|
+
bundle install --relock
|
47
|
+
rake
|
48
|
+
|
49
|
+
This will run the test suite, which should come back all green! Then
|
50
|
+
you're good to go!
|
51
|
+
|
52
|
+
## Special Thanks
|
53
|
+
|
54
|
+
These folks went above and beyond with contributions to the virtualbox gem, and
|
55
|
+
for that, I have to say "thanks!"
|
56
|
+
|
57
|
+
* [Mitchell Hashimoto](https://github.com/mitchellh)
|
58
|
+
* [Kieran Pilkington](https://github.com/KieranP)
|
59
|
+
* [Aleksey Palazhchenko](https://github.com/AlekSi)
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'virtualbox-com'
|
3
|
+
|
4
|
+
# Shortcut
|
5
|
+
lib = VirtualBox::COM
|
6
|
+
|
7
|
+
# Name of the first VM
|
8
|
+
puts lib.virtualbox.machines[0].name
|
9
|
+
|
10
|
+
# Groups of the VM named 'Windows'
|
11
|
+
puts lib.virtualbox.find_machine('Windows').groups
|
12
|
+
|
13
|
+
# Register a passive listener
|
14
|
+
begin
|
15
|
+
s = VirtualBox::COM.virtualbox.event_source
|
16
|
+
l = s.create_listener
|
17
|
+
# Listen on all events with a passive listener
|
18
|
+
s.register_listener(l, [ :any ], false)
|
19
|
+
while true do
|
20
|
+
# Get event
|
21
|
+
if e = s.get_event(l, 1000)
|
22
|
+
case e.type
|
23
|
+
when :on_guest_property_changed
|
24
|
+
# If GuestProperyChanged cast the event to the
|
25
|
+
# model having the most information
|
26
|
+
n = e.cast(:GuestPropertyChangedEvent)
|
27
|
+
puts "GuestProperty: #{n.machine_id} / #{n.name} / #{n.value}"
|
28
|
+
else
|
29
|
+
# Display event type
|
30
|
+
puts "Event: #{e.type}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# If event is waitable, acknowlege we have finished with it
|
34
|
+
if e.waitable
|
35
|
+
e.source.event_processed(l, e)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
rescue VirtualBox::COM::ObjectNotFoundException
|
40
|
+
# Could just be because we weren't able to collect data fast
|
41
|
+
# enough, so VirtualBox unregistered our listener
|
42
|
+
retry
|
43
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'virtualbox/com.rb'
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module VirtualBox
|
2
|
+
module COM
|
3
|
+
# Versions of Virtualbox that are supported
|
4
|
+
SUPPORTED_VERSIONS = {
|
5
|
+
"4.2" => [ "3b2f08eb-b810-4715-bee0-bb06b9880ad2",
|
6
|
+
"12f4dcdb-12b2-4ec1-b7cd-ddd9f6c5bf4d" ],
|
7
|
+
}
|
8
|
+
|
9
|
+
# The Model module will hold all the model descriptions that will
|
10
|
+
# be loaded according to the VirtualBox version
|
11
|
+
module Model
|
12
|
+
def self.get(name)
|
13
|
+
self.const_get(name, false)
|
14
|
+
rescue NameError
|
15
|
+
raise ModelNotFoundException, name
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.create(name, *args)
|
19
|
+
self.get(name).new(*args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Information about VirtualBox version
|
24
|
+
def self.supported? ; !version.nil? ; end
|
25
|
+
def self.version ; virtualbox.version_normalized rescue nil ; end
|
26
|
+
def self.revision ; virtualbox.revision.to_s rescue nil ; end
|
27
|
+
|
28
|
+
# Helpers for inclusion
|
29
|
+
def virtualbox ; COM.virtualbox ; end
|
30
|
+
def session ; COM.session ; end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# Exceptions
|
36
|
+
require_relative 'com/exceptions'
|
37
|
+
|
38
|
+
# Abstract class for model definitions
|
39
|
+
require_relative 'com/abstract_enum'
|
40
|
+
require_relative 'com/abstract_interface'
|
41
|
+
|
42
|
+
# Classes
|
43
|
+
require_relative 'com/iid'
|
44
|
+
|
45
|
+
# Implementation
|
46
|
+
# It needs to add the following to VirtualBox::COM
|
47
|
+
# - Methods: virtualbox, session
|
48
|
+
# - Class : Implementer
|
49
|
+
# - Types : INT8, INT16, INT32, INT64, UINT8, UINT16, UINT32, UINT64,
|
50
|
+
# WSTRING, BOOL
|
51
|
+
require_relative 'com/xpcomc-ffi'
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative "abstract_model"
|
2
|
+
|
3
|
+
module VirtualBox
|
4
|
+
module COM
|
5
|
+
|
6
|
+
# Represents a C enum type. Provides functionality to easily convert
|
7
|
+
# an int value to its proper symbol within the enum.
|
8
|
+
class AbstractEnum < AbstractModel
|
9
|
+
extend Enumerable
|
10
|
+
|
11
|
+
# Defines the mapping of int => symbol for the given Enum.
|
12
|
+
# The parameter to this can be an Array or Hash or anything which
|
13
|
+
# respond to `each` and yield a key/value pair.
|
14
|
+
# If a value appear more than once, only the first is kept
|
15
|
+
# If value is left nil, it will return the current mapping
|
16
|
+
def self.map(value = nil)
|
17
|
+
if value
|
18
|
+
m, r = {}, {}
|
19
|
+
if Array === value
|
20
|
+
then value.each_index {|i| m[value[i]] = i; r[i] = value[i] }
|
21
|
+
else value.each {|k,v| m[k] = v; r[v] ||= k }
|
22
|
+
end
|
23
|
+
@map, @reverse_map = m, r
|
24
|
+
end
|
25
|
+
|
26
|
+
@map
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the symbol associated with the given key
|
30
|
+
def self.[](index)
|
31
|
+
case index
|
32
|
+
when Symbol then @map[index]
|
33
|
+
else @reverse_map[index]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the index associated with a value
|
38
|
+
def self.index(key)
|
39
|
+
@map[key]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Iterate over the enum, yielding each item to a block.
|
43
|
+
def self.each
|
44
|
+
@map.each do |key, value|
|
45
|
+
yield key
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require_relative "abstract_model"
|
2
|
+
|
3
|
+
module VirtualBox
|
4
|
+
module COM
|
5
|
+
|
6
|
+
#
|
7
|
+
# # Defining an Interface
|
8
|
+
#
|
9
|
+
# Defining an interface is done by subclassing AbstractInterface and
|
10
|
+
# using the provided class methods to define the COM methods and
|
11
|
+
# properties. A small example class is shown below:
|
12
|
+
#
|
13
|
+
# class Time < AbstractInterface
|
14
|
+
# function :now, [[:out, :uint]]
|
15
|
+
# property :hour, :uint
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # Accessing an Interface
|
19
|
+
#
|
20
|
+
#
|
21
|
+
# # Assume `time` was retrieved already
|
22
|
+
# puts time.foo.to_s
|
23
|
+
# time.hour = 20
|
24
|
+
# x = time.now
|
25
|
+
#
|
26
|
+
# The above example shows how the properties and functions can be used
|
27
|
+
# with a given interface.
|
28
|
+
#
|
29
|
+
class AbstractInterface < AbstractModel
|
30
|
+
attr_reader :implementer
|
31
|
+
|
32
|
+
class << self
|
33
|
+
|
34
|
+
# Extends the current model with another one.
|
35
|
+
# Note that redefining functions or properties is not supported.
|
36
|
+
def extends(model)
|
37
|
+
Model.get(model).members.each do |spec|
|
38
|
+
if h.include?(spec.name)
|
39
|
+
raise "redefining of #{spec.name} is not supported"
|
40
|
+
end
|
41
|
+
h[spec.name] = spec
|
42
|
+
end
|
43
|
+
rescue ModelNotFoundException
|
44
|
+
raise "trying to extend an unknown model (#{model})"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Adds a function to the interface
|
48
|
+
def function(name, type, args, opts={})
|
49
|
+
h[name] = Spec::Function.new(name, type, args, opts)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Adds a property to the interface
|
53
|
+
def property(name, type, opts={})
|
54
|
+
h[name] = Spec::Property.new(name, type, opts)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Perform final setup
|
58
|
+
def setup
|
59
|
+
members.each {|spec| name = spec.name
|
60
|
+
case spec
|
61
|
+
when Spec::Function
|
62
|
+
define_method(name) { |*args|
|
63
|
+
@implementer.call_function(spec, *args)
|
64
|
+
} unless spec.hide?
|
65
|
+
when Spec::Property
|
66
|
+
define_method(name) {
|
67
|
+
@implementer.read_property(spec)
|
68
|
+
} unless spec.hide?
|
69
|
+
define_method(:"#{name}=") { |value|
|
70
|
+
@implementer.write_property(spec, value)
|
71
|
+
} unless spec.hide? || spec.readonly?
|
72
|
+
end
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
# Get a member by name
|
77
|
+
def member(name)
|
78
|
+
h[name]
|
79
|
+
end
|
80
|
+
|
81
|
+
# List of members (Spec::*)
|
82
|
+
def members
|
83
|
+
h.values
|
84
|
+
end
|
85
|
+
|
86
|
+
# List of functions (Spec::Function)
|
87
|
+
def functions
|
88
|
+
members.select {|s| s.kind_of?(Spec::Function) }
|
89
|
+
end
|
90
|
+
|
91
|
+
# List if properties (Spec::Property)
|
92
|
+
def properties
|
93
|
+
members.select {|s| s.kind_of?(Spec::Property) }
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
private
|
98
|
+
def h ; @h ||= {} ; end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
# Initializes the interface with the given implementer
|
103
|
+
def initialize(*args)
|
104
|
+
@args = args
|
105
|
+
@implementer = Implementer.new(self, *args)
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# Cast to another model
|
110
|
+
def cast(name)
|
111
|
+
@implementer.cast(name, *@args)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Reads a property with the given name
|
115
|
+
def read_property(name)
|
116
|
+
spec = self.class.member(name)
|
117
|
+
raise "#{name} is not a property" unless spec.kind_of?(Spec::Property)
|
118
|
+
@implementer.read_property(spec)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Writes a property with the given name
|
122
|
+
def write_property(name, value)
|
123
|
+
spec = self.class.member(name)
|
124
|
+
raise "#{name} is not a property" unless spec.kind_of?(Spec::Property)
|
125
|
+
raise "property #{name} is readonly" if spec.readonly?
|
126
|
+
@implementer.write_property(spec, value)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Calls a function with the given name
|
130
|
+
def call_function(name, *args)
|
131
|
+
spec = self.class.member(name)
|
132
|
+
raise "#{name} is not a function" unless spec.kind_of?(Spec::Function)
|
133
|
+
@implementer.call_function(spec, args)
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
# Concise inspect
|
138
|
+
def inspect
|
139
|
+
"#<#{self.class.name}>"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module VirtualBox
|
2
|
+
module COM
|
3
|
+
|
4
|
+
class ModelNotFoundException < ::Exception; end
|
5
|
+
|
6
|
+
class COMException < ::Exception
|
7
|
+
attr_accessor :data
|
8
|
+
|
9
|
+
def initialize(data={})
|
10
|
+
@data = data
|
11
|
+
super("Error in API call to #{data[:function]}: #{data[:code]}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class NotImplementedException < COMException; end
|
16
|
+
class ObjectNotFoundException < COMException; end
|
17
|
+
class InvalidVMStateException < COMException; end
|
18
|
+
class VMErrorException < COMException; end
|
19
|
+
class FileErrorException < COMException; end
|
20
|
+
class SubsystemException < COMException; end
|
21
|
+
class PDMException < COMException; end
|
22
|
+
class InvalidObjectStateException < COMException; end
|
23
|
+
class HostErrorException < COMException; end
|
24
|
+
class NotSupportedException < COMException; end
|
25
|
+
class XMLErrorException < COMException; end
|
26
|
+
class InvalidSessionStateException < COMException; end
|
27
|
+
class ObjectInUseException < COMException; end
|
28
|
+
class InvalidArgException < COMException; end
|
29
|
+
class NoInterfaceException < COMException; end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|