virtualbox-ws 0.0.5 → 0.0.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +60 -0
- data/lib/core_ext/string.rb +20 -1
- data/lib/virtualbox/base.rb +26 -65
- data/lib/virtualbox/classes/dhcp_server.rb +2 -0
- data/lib/virtualbox/classes/events/cpu_changed_event.rb +2 -0
- data/lib/virtualbox/classes/events/cpu_execution_cap_changed_event.rb +2 -0
- data/lib/virtualbox/classes/events/nat_redirect_event.rb +2 -0
- data/lib/virtualbox/classes/events/usb_controller_changed_event.rb +3 -0
- data/lib/virtualbox/classes/events/usb_device_state_changed_event.rb +2 -0
- data/lib/virtualbox/classes/events/vrde_server_changed_event.rb +3 -0
- data/lib/virtualbox/classes/events/vrde_server_info_changed_event.rb +3 -0
- data/lib/virtualbox/classes/machine.rb +1 -1
- data/lib/virtualbox/classes/nat_engine.rb +2 -0
- data/lib/virtualbox/classes/nat_network.rb +2 -0
- data/lib/virtualbox/classes/usb_controller.rb +2 -0
- data/lib/virtualbox/classes/usb_device.rb +2 -0
- data/lib/virtualbox/classes/usb_device_filter.rb +2 -0
- data/lib/virtualbox/classes/usb_device_filters.rb +2 -0
- data/lib/virtualbox/classes/vfs_explorer.rb +2 -0
- data/lib/virtualbox/classes/vrde_server.rb +2 -0
- data/lib/virtualbox/classes/vrde_server_info.rb +2 -0
- data/lib/virtualbox/classes/websession_manager.rb +2 -3
- data/lib/virtualbox/configuration.rb +22 -24
- data/lib/virtualbox/exceptions.rb +17 -19
- data/lib/virtualbox/version.rb +1 -1
- data/lib/virtualbox/webservice.rb +74 -79
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14809e7c2980b37be12543d76529d87b45434fe9
|
4
|
+
data.tar.gz: 9f934f1477fe90ef9010247a64eec2695443adea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdf1b1d99b76fca4015a7005f848eef358d9a26fc2877b0f4b1ac9a952b508e6099cc433a93e5bfb22d6d908333b9a097baea278c70855a46528ca4d479b2684
|
7
|
+
data.tar.gz: 6c22b4037d12e6320f6d1b18aea8b5b57da6ae425a0d97c77361687faef717ca0c60c3dbda91cd3a89943c4a34364ff4c20d3ec9aabde63a4d999b2a6a59687e
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -89,4 +89,64 @@ irb> virtual_box.register_machine(:machine => machine)
|
|
89
89
|
```
|
90
90
|
irb> machine.launch_vm_process(:session => web_session.get_session_object)
|
91
91
|
=> #<VBox::Progress:0x00000005934040 @ref="47efe040fcc25df7-000000000000001f">
|
92
|
+
```
|
93
|
+
|
94
|
+
Example
|
95
|
+
-------
|
96
|
+
|
97
|
+
This is an example of creating a VM that is ready for Ubuntu x64 to be installed on it
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
require 'virtualbox-ws'
|
101
|
+
|
102
|
+
# Connect to the web service and logon
|
103
|
+
# Get session object for future use
|
104
|
+
web_session = VBox::WebsessionManager.new
|
105
|
+
virtual_box = web_session.logon
|
106
|
+
session = web_session.get_session_object
|
107
|
+
|
108
|
+
# Create an Ubuntu x64 VM
|
109
|
+
machine = virtual_box.create_machine(:name => 'machine_1112678', :os_type_id => 'Ubuntu_64')
|
110
|
+
virtual_box.register_machine(:machine => machine)
|
111
|
+
|
112
|
+
# Create a 50GB hard disk
|
113
|
+
hard_disk = virtual_box.create_hard_disk(:format => 'vdi', :location => machine.settings_file_path.gsub('vbox', 'vdi'))
|
114
|
+
hard_disk.create_base_storage(:logical_size => 50000000000)
|
115
|
+
|
116
|
+
# Lock the VM for editing and obtain a mutable instance
|
117
|
+
machine.lock_machine(:session => session)
|
118
|
+
mutable = session.machine
|
119
|
+
|
120
|
+
# Set some common properties
|
121
|
+
mutable.cpu_count = 4
|
122
|
+
mutable.memory_size = 1024
|
123
|
+
mutable.rtc_use_utc = true
|
124
|
+
mutable.vram_size = 16
|
125
|
+
mutable.accelerate_3d_enabled = true
|
126
|
+
mutable.audio_adapter.enabled = true
|
127
|
+
|
128
|
+
# Add the hard disk
|
129
|
+
mutable.add_storage_controller(:name => 'SATA1', :connection_type => 'SATA')
|
130
|
+
mutable.attach_device(:name => 'SATA1', :type => 'HardDisk', :medium => hard_disk)
|
131
|
+
|
132
|
+
# Add an ISO image
|
133
|
+
mutable.add_storage_controller(:name => 'IDE1', :connection_type => 'IDE')
|
134
|
+
iso = virtual_box.open_medium(:location => '/home/ay/Downloads/ubuntu-12.04.3-server-amd64.iso', :device_type => 'DVD')
|
135
|
+
mutable.attach_device(:name => 'IDE1', :type => 'DVD', :medium => iso)
|
136
|
+
|
137
|
+
# Set network adapter to bridged interface
|
138
|
+
network_adapter = mutable.get_network_adapter(:slot => 0)
|
139
|
+
network_adapter.attachment_type = 'Bridged'
|
140
|
+
network_adapter.bridged_interface = virtual_box.host.network_interfaces.first.name
|
141
|
+
|
142
|
+
# Enable USB
|
143
|
+
mutable.add_usb_controller(:name => 'USB1', :type => 'OHCI')
|
144
|
+
mutable.add_usb_controller(:name => 'USB2', :type => 'EHCI')
|
145
|
+
|
146
|
+
# Save changes and unlock the VM
|
147
|
+
mutable.save_settings
|
148
|
+
session.unlock_machine
|
149
|
+
|
150
|
+
# Start the VM
|
151
|
+
machine.launch_vm_process(:session => session)
|
92
152
|
```
|
data/lib/core_ext/string.rb
CHANGED
@@ -1,6 +1,25 @@
|
|
1
1
|
class String
|
2
2
|
def to_a
|
3
|
-
self
|
3
|
+
[] << self
|
4
|
+
end
|
5
|
+
|
6
|
+
def to_num
|
7
|
+
if !self.match(/^[0-9]+$/).nil?
|
8
|
+
Integer(self)
|
9
|
+
elsif !self.match(/^[0-9]+\.[0-9]+$/).nil?
|
10
|
+
Float(self)
|
11
|
+
else
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def vbox_class
|
17
|
+
VBox::ManagedObjectRef.new(self).get_interface_name
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_vbox_object(cls)
|
21
|
+
return self if cls.nil?
|
22
|
+
VBox.const_get(cls[1..-1]).new(self)
|
4
23
|
end
|
5
24
|
|
6
25
|
def to_underscore
|
data/lib/virtualbox/base.rb
CHANGED
@@ -18,11 +18,11 @@ module VBox
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.starts_with_acronym
|
21
|
-
define_method(:
|
21
|
+
define_method(:acronym) {}
|
22
22
|
end
|
23
23
|
|
24
24
|
def self.soap_method(method_name, modifier=nil)
|
25
|
-
is_acronym_part =
|
25
|
+
is_acronym_part = self.name.split('::').last.match(/^[A-Z]{2,}/).nil? ? '_' : ''
|
26
26
|
modifier_part = modifier.nil? ? '' : modifier + '_'
|
27
27
|
"i#{is_acronym_part}#{class_name}_#{modifier_part}#{method_name}".to_sym
|
28
28
|
end
|
@@ -39,54 +39,24 @@ module VBox
|
|
39
39
|
self.class.class_name
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
43
|
-
if value.is_a?(Array)
|
44
|
-
value.map do |item|
|
45
|
-
begin
|
46
|
-
Integer(item)
|
47
|
-
rescue ArgumentError
|
48
|
-
item
|
49
|
-
end
|
50
|
-
end
|
51
|
-
else
|
52
|
-
begin
|
53
|
-
Integer(value)
|
54
|
-
rescue ArgumentError
|
55
|
-
value
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def classify(result, force_array=false)
|
42
|
+
def process_result(result, force_array=false)
|
61
43
|
if force_array
|
62
44
|
return [] if result.nil?
|
63
45
|
result = result.to_a
|
64
|
-
|
65
|
-
|
66
|
-
# in the array are objects of the same class
|
67
|
-
val = result[0]
|
46
|
+
vbox_class = result.first.vbox_class
|
47
|
+
result.map { |item| item.to_vbox_object(vbox_class) }
|
68
48
|
else
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
# Get VirtualBox interface name
|
79
|
-
class_str = ManagedObjectRef.new(val).get_interface_name
|
80
|
-
|
81
|
-
# ManagedObjectRef.get_interface_name returns nil
|
82
|
-
# for inexisting object reference
|
83
|
-
if class_str.nil?
|
84
|
-
result
|
85
|
-
else
|
86
|
-
if force_array
|
87
|
-
result.to_a.map { |item| VBox.const_get(class_str[1..-1]).new(item) }
|
49
|
+
return if result.nil?
|
50
|
+
if result.is_a?(Array)
|
51
|
+
result.map { |item| process_result(item) }
|
52
|
+
elsif result.is_a?(Hash)
|
53
|
+
result.update(result) { |_, value| process_result(value) }
|
54
|
+
elsif !!result == result
|
55
|
+
result
|
56
|
+
elsif !result.match(/^[0-9a-f]{16}-[0-9a-f]{16}$/).nil?
|
57
|
+
result.to_vbox_object(result.vbox_class)
|
88
58
|
else
|
89
|
-
|
59
|
+
result.to_num
|
90
60
|
end
|
91
61
|
end
|
92
62
|
end
|
@@ -95,21 +65,26 @@ module VBox
|
|
95
65
|
force_array = options[:force_array]
|
96
66
|
force_tag = options[:force_tag]
|
97
67
|
|
98
|
-
# A special case for VirtualBox methods that have lowercase 'v' in IPv6
|
99
68
|
if name.to_s.start_with?('ipv6') || name.to_s.include?('advertise_default_ipv6_route_enabled')
|
100
|
-
|
69
|
+
native_name = name.to_s.gsub('ipv6', 'i_pv6').to_sym
|
70
|
+
elsif name.to_s.include?('_3d_')
|
71
|
+
native_name = name.to_s.gsub('_3d_', '3_d_').to_sym
|
72
|
+
elsif name.to_s.include?('_2d_')
|
73
|
+
native_name = name.to_s.gsub('_2d_', '2_d_').to_sym
|
74
|
+
else
|
75
|
+
native_name = name
|
101
76
|
end
|
102
77
|
|
103
78
|
define_method(name) do
|
104
|
-
result = WebService.send_request(soap_method(
|
79
|
+
result = WebService.send_request(soap_method(native_name, 'get'), _this)
|
105
80
|
process_result(result, force_array)
|
106
81
|
end
|
107
82
|
|
108
83
|
define_method("#{name}=") do |value|
|
109
|
-
soap_message = {force_tag ? force_tag :
|
110
|
-
result = WebService.send_request(soap_method(
|
84
|
+
soap_message = {force_tag ? force_tag : native_name => value}
|
85
|
+
result = WebService.send_request(soap_method(native_name, 'set'), _this.merge(soap_message))
|
111
86
|
process_result(result)
|
112
|
-
end if WebService.operations.include?(soap_method(
|
87
|
+
end if WebService.operations.include?(soap_method(native_name, 'set'))
|
113
88
|
end
|
114
89
|
|
115
90
|
def self.vb_method(name, options={})
|
@@ -122,19 +97,5 @@ module VBox
|
|
122
97
|
process_result(result, force_array)
|
123
98
|
end
|
124
99
|
end
|
125
|
-
|
126
|
-
def process_result(result, force_array=false)
|
127
|
-
if force_array
|
128
|
-
classify(result, true)
|
129
|
-
else
|
130
|
-
if result.is_a?(Array)
|
131
|
-
result.map do |item|
|
132
|
-
item.is_a?(Hash) ? item.update(item) { |_, value| classify(value) } : classify(item)
|
133
|
-
end
|
134
|
-
else
|
135
|
-
classify(result)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
100
|
end
|
140
101
|
end
|
@@ -18,9 +18,8 @@ module VBox
|
|
18
18
|
def logon
|
19
19
|
args = Hash[:username => WebService.configuration.vboxweb_user,
|
20
20
|
:password => WebService.configuration.vboxweb_pass]
|
21
|
-
|
22
|
-
@ref
|
23
|
-
VirtualBox.new(key)
|
21
|
+
@ref = WebService.send_request(:i_websession_manager_logon, args)
|
22
|
+
VirtualBox.new(@ref)
|
24
23
|
end
|
25
24
|
|
26
25
|
def logoff
|
@@ -1,35 +1,33 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
|
4
|
-
module VBox
|
5
|
-
|
6
|
-
class Configuration
|
4
|
+
module VBox::WebService
|
5
|
+
class Configuration
|
7
6
|
|
8
|
-
|
7
|
+
attr_accessor :vboxweb_host, :vboxweb_port, :vboxweb_user, :vboxweb_pass, :log_level, :logger
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
def log_level=(log_level)
|
21
|
-
@log_level = ['ERROR', 'INFO', 'DEBUG'].include?(log_level) ? log_level : 'ERROR'
|
22
|
-
@logger.level = Logger.const_get(@log_level)
|
23
|
-
end
|
9
|
+
def initialize
|
10
|
+
@vboxweb_host = ENV['VBOXWEB_HOST'] || '127.0.0.1'
|
11
|
+
@vboxweb_port = ENV['VBOXWEB_PORT'] || '18083'
|
12
|
+
@vboxweb_user = ENV['VBOXWEB_USER']
|
13
|
+
@vboxweb_pass = ENV['VBOXWEB_PASS']
|
14
|
+
@log_level = ENV['VBOXWEB_LOGGING'] || 'ERROR'
|
15
|
+
@logger = Logger.new(STDOUT)
|
16
|
+
@logger.level = Logger.const_get(@log_level)
|
24
17
|
end
|
25
18
|
|
26
|
-
|
27
|
-
|
19
|
+
def log_level=(log_level)
|
20
|
+
@log_level = ['ERROR', 'INFO', 'DEBUG'].include?(log_level) ? log_level : 'ERROR'
|
21
|
+
@logger.level = Logger.const_get(@log_level)
|
28
22
|
end
|
23
|
+
end
|
29
24
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
class << self
|
26
|
+
attr_accessor :configuration
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.configure
|
30
|
+
self.configuration ||= Configuration.new
|
31
|
+
yield configuration
|
34
32
|
end
|
35
33
|
end
|
@@ -1,28 +1,26 @@
|
|
1
|
-
module VBox
|
2
|
-
|
3
|
-
class Error < StandardError; end
|
1
|
+
module VBox::WebService
|
2
|
+
class Error < StandardError; end
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
class ConnectionError < Error
|
5
|
+
def initialize(endpoint, message)
|
6
|
+
@endpoint = endpoint
|
7
|
+
@message = message
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
end
|
10
|
+
def to_s
|
11
|
+
"Could not connect to VirtualBox SOAP Web Service at #{@endpoint}. #{@message}"
|
14
12
|
end
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
15
|
+
class NoWebServiceError < ConnectionError
|
16
|
+
def initialize(endpoint, message = 'No VirtualBox SOAP service found')
|
17
|
+
super
|
20
18
|
end
|
19
|
+
end
|
21
20
|
|
22
|
-
|
21
|
+
class UnknownError < Error; end
|
23
22
|
|
24
|
-
|
23
|
+
class ArgumentError < Error; end
|
25
24
|
|
26
|
-
|
27
|
-
end
|
25
|
+
class NotImplementedError < Error; end
|
28
26
|
end
|
data/lib/virtualbox/version.rb
CHANGED
@@ -1,104 +1,99 @@
|
|
1
1
|
require 'savon'
|
2
2
|
|
3
3
|
|
4
|
-
module VBox
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
self.configuration ||= Configuration.new
|
4
|
+
module VBox::WebService
|
5
|
+
class << self
|
6
|
+
def connect
|
7
|
+
# Initialize configuration here in case if it was not initialized in client
|
8
|
+
self.configuration ||= Configuration.new
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
host = configuration.vboxweb_host
|
11
|
+
port = configuration.vboxweb_port
|
12
|
+
log_level = configuration.log_level
|
13
|
+
@logger = configuration.logger
|
15
14
|
|
16
|
-
|
17
|
-
|
15
|
+
# Savon XML logging
|
16
|
+
savon_debug = log_level == 'DEBUG'
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
endpoint = "http://#{host}:#{port}"
|
19
|
+
wsdl = endpoint + '/?wsdl'
|
20
|
+
@logger.info("VirtualBox SOAP web service endpoint: #{endpoint}")
|
21
|
+
@logger.info("VirtualBox SOAP web service WSDL: #{wsdl}")
|
23
22
|
|
24
|
-
|
25
|
-
|
23
|
+
# Create web service connection
|
24
|
+
@conn = Savon.client(:wsdl => wsdl, :endpoint => endpoint, :log => savon_debug, :pretty_print_xml => savon_debug)
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
26
|
+
# Check if we really connected to a VirtualBox SOAP web service
|
27
|
+
unless operations.include?(:i_websession_manager_logon)
|
28
|
+
@logger.fatal("Could not connect to VirtualBox SOAP Web Service at #{endpoint}. No VirtualBox SOAP service found")
|
29
|
+
raise NoWebServiceError.new(endpoint)
|
32
30
|
end
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
def operations
|
34
|
+
@conn.operations
|
35
|
+
end
|
37
36
|
|
38
|
-
|
39
|
-
|
37
|
+
def send_request(soap_method, soap_message)
|
38
|
+
@logger.info("Request operation: #{soap_method}")
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
# Filter out the password string
|
41
|
+
log_soap_message = soap_message.clone
|
42
|
+
if soap_method == :i_websession_manager_logon
|
43
|
+
log_soap_message[:password] = '<filtered>' if log_soap_message.has_key?(:password)
|
44
|
+
end
|
46
45
|
|
47
|
-
|
46
|
+
@logger.info("Request message: #{log_soap_message}")
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
parse_response(response)
|
48
|
+
begin
|
49
|
+
response = @conn.call(soap_method, :message => soap_message)
|
50
|
+
rescue Savon::SOAPFault => e
|
51
|
+
@logger.debug(e.message)
|
52
|
+
parse_soap_fault(e.message)
|
53
|
+
rescue Savon::HTTPError => e
|
54
|
+
@logger.error(e.message)
|
55
|
+
raise
|
59
56
|
end
|
57
|
+
parse_response(response)
|
58
|
+
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
else
|
67
|
-
argument = message.match(/<\S+>/).to_s[1..-2].to_underscore
|
68
|
-
raise ArgumentError, "Argument #{argument} is of invalid data type"
|
69
|
-
end
|
60
|
+
def parse_soap_fault(message)
|
61
|
+
error_code = message.match(/0x[[:xdigit:]]+/)
|
62
|
+
if error_code.nil?
|
63
|
+
if message.match(/Validation constraint violation: data type mismatch in element <\S+>/).nil?
|
64
|
+
raise UnknownError, message
|
70
65
|
else
|
71
|
-
|
72
|
-
raise
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
66
|
+
argument = message.match(/<\S+>/).to_s[1..-2].to_underscore
|
67
|
+
raise ArgumentError, "Argument #{argument} is of invalid data type"
|
68
|
+
end
|
69
|
+
else
|
70
|
+
error_message = message.split("(SOAP-ENV:Client) VirtualBox error: rc=#{error_code} ")[1].split(" (#{error_code})")[0]
|
71
|
+
raise UnknownError, message if error_message.nil?
|
72
|
+
argument = error_message.match(/\sa[A-Z]\S+\s/)
|
73
|
+
if argument.nil?
|
74
|
+
if error_message.match(/Method \S+ is not implemented/).nil?
|
75
|
+
raise Error, error_message
|
80
76
|
else
|
81
|
-
|
82
|
-
gsub!(/\s\(must be .*\)/, '')
|
83
|
-
raise ArgumentError, error_message
|
77
|
+
raise NotImplementedError, error_message
|
84
78
|
end
|
79
|
+
else
|
80
|
+
error_message.gsub!(argument.to_s.strip, argument.to_s.strip[1..-1].to_underscore).
|
81
|
+
gsub!(/\s\(must be .*\)/, '')
|
82
|
+
raise ArgumentError, error_message
|
85
83
|
end
|
86
84
|
end
|
85
|
+
end
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
else
|
99
|
-
response_struct[:returnval]
|
100
|
-
end
|
101
|
-
end
|
87
|
+
def parse_response(response)
|
88
|
+
@logger.info("Response: #{response.body}")
|
89
|
+
response_struct = response.body[response.body.keys[0]]
|
90
|
+
return if response_struct.nil?
|
91
|
+
if response_struct.keys.length > 1
|
92
|
+
returnval = response_struct[:returnval].nil? || response_struct[:returnval]
|
93
|
+
response_struct.delete(:returnval)
|
94
|
+
[returnval, response_struct]
|
95
|
+
else
|
96
|
+
response_struct[:returnval]
|
102
97
|
end
|
103
98
|
end
|
104
99
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: virtualbox-ws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andriy Yurchuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: require_all
|