virtualbox-com 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ doc/*
2
+ .yardoc/*
3
+ pkg/*
4
+ test/coverage/*
5
+ .bundle/*
6
+ Gemfile.lock
7
+ test.rb
8
+ *.rbc
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ # Gems required for development only.
6
+ group :development do
7
+ gem "ffi"
8
+ gem "nokogiri"
9
+ end
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
@@ -0,0 +1,8 @@
1
+ # -*- ruby -*-
2
+ require "rbconfig"
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+
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)
@@ -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,14 @@
1
+ module VirtualBox
2
+ module COM
3
+
4
+ class AbstractModel
5
+ def self.iid(str)
6
+ const_set(:IID, IID.new(str))
7
+ end
8
+
9
+ def self.setup(opts={})
10
+ end
11
+ end
12
+
13
+ end
14
+ 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