virtual_box 0.0.1 → 0.1.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.
Files changed (47) hide show
  1. data/.autotest +9 -0
  2. data/.document +5 -0
  3. data/.project +12 -0
  4. data/.rspec +1 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +44 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.markdown +67 -0
  9. data/Rakefile +35 -22
  10. data/VERSION +1 -0
  11. data/lib/virtual_box/board.rb +287 -0
  12. data/lib/virtual_box/cli.rb +20 -0
  13. data/lib/virtual_box/dhcp.rb +149 -0
  14. data/lib/virtual_box/disk.rb +138 -0
  15. data/lib/virtual_box/io_bus.rb +261 -0
  16. data/lib/virtual_box/net.rb +144 -0
  17. data/lib/virtual_box/nic.rb +213 -0
  18. data/lib/virtual_box/version.rb +37 -24
  19. data/lib/virtual_box/vm.rb +289 -24
  20. data/lib/virtual_box.rb +14 -9
  21. data/test/helper.rb +24 -0
  22. data/test/tasks/tinycore.rake +378 -0
  23. data/test/virtual_box/board_test.rb +39 -0
  24. data/test/virtual_box/cli_test.rb +33 -0
  25. data/test/virtual_box/dhcp_test.rb +52 -0
  26. data/test/virtual_box/disk_test.rb +116 -0
  27. data/test/virtual_box/integration_test.rb +53 -0
  28. data/test/virtual_box/io_bus_test.rb +54 -0
  29. data/test/virtual_box/net_test.rb +80 -0
  30. data/test/virtual_box/nic_test.rb +50 -0
  31. data/test/virtual_box/version_test.rb +71 -0
  32. data/test/virtual_box/vm_test.rb +55 -0
  33. data/virtual_box.gemspec +81 -22
  34. metadata +208 -89
  35. data/CHANGELOG +0 -1
  36. data/LICENSE +0 -21
  37. data/Manifest +0 -17
  38. data/README.textile +0 -19
  39. data/lib/virtual_box/command_line.rb +0 -27
  40. data/lib/virtual_box/vm/general_settings.rb +0 -136
  41. data/lib/virtual_box/vm/identity.rb +0 -43
  42. data/lib/virtual_box/vm/lifecycle.rb +0 -42
  43. data/test/command_line_test.rb +0 -19
  44. data/test/general_settings_test.rb +0 -20
  45. data/test/lifecycle_test.rb +0 -64
  46. data/test/version_test.rb +0 -56
  47. data/testdata/golden_general_params.txt +0 -1
data/.autotest ADDED
@@ -0,0 +1,9 @@
1
+ Autotest.add_hook :initialize do |autotest|
2
+ autotest.add_exception '.git'
3
+ autotest.add_mapping %r{lib/virtual_box/.*\.rb$} do |file, match|
4
+ p match
5
+ autotest.files_matching %r{spec/.*_spec\.rb$}
6
+ end
7
+ p autotest.mappings
8
+ false
9
+ end
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.project ADDED
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>virtual_box</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ </buildSpec>
9
+ <natures>
10
+ <nature>org.radrails.rails.core.railsnature</nature>
11
+ </natures>
12
+ </projectDescription>
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source :rubygems
2
+
3
+ gem 'hashie', '>= 0.4.0'
4
+ gem 'uuid', '>= 2.3.5'
5
+
6
+ group :development do
7
+ gem 'bundler', '>= 1.1.3'
8
+ gem 'jeweler', '>= 1.8.3'
9
+ gem 'minitest', '>= 2.12.1'
10
+ gem 'mocha', '>= 0.11.0', :require => false
11
+ gem 'net-ssh', '>= 2.3.0', :require => 'net/ssh'
12
+ gem 'simplecov', '>= 0.6.1'
13
+ gem 'yard', '>= 0.7.5'
14
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,44 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ hashie (1.2.0)
6
+ jeweler (1.8.3)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rdoc
11
+ json (1.7.0)
12
+ macaddr (1.5.0)
13
+ systemu (>= 2.4.0)
14
+ metaclass (0.0.1)
15
+ minitest (2.12.1)
16
+ mocha (0.11.3)
17
+ metaclass (~> 0.0.1)
18
+ multi_json (1.3.4)
19
+ net-ssh (2.3.0)
20
+ rake (0.9.2.2)
21
+ rdoc (3.12)
22
+ json (~> 1.4)
23
+ simplecov (0.6.2)
24
+ multi_json (~> 1.3)
25
+ simplecov-html (~> 0.5.3)
26
+ simplecov-html (0.5.3)
27
+ systemu (2.5.0)
28
+ uuid (2.3.5)
29
+ macaddr (~> 1.0)
30
+ yard (0.8.0)
31
+
32
+ PLATFORMS
33
+ ruby
34
+
35
+ DEPENDENCIES
36
+ bundler (>= 1.1.3)
37
+ hashie (>= 0.4.0)
38
+ jeweler (>= 1.8.3)
39
+ minitest (>= 2.12.1)
40
+ mocha (>= 0.11.0)
41
+ net-ssh (>= 2.3.0)
42
+ simplecov (>= 0.6.1)
43
+ uuid (>= 2.3.5)
44
+ yard (>= 0.7.5)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Victor Costan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,67 @@
1
+ # virtual_box
2
+
3
+ This gem is a Ruby API for VirtualBox, Sun's open-source virtualization software
4
+ that supports Linux, Mac OS X, and Windows.
5
+
6
+
7
+ ## Features
8
+
9
+ Currently, the gem supports the following features:
10
+ * VM creation and removal
11
+ * VM start, and stop
12
+ * Disk (VDI, VMDK, VHD) and DVD (ISO) images
13
+ * NAT, bridged, host-only and internal networking
14
+ * DHCP configuration for host-only and internal networks
15
+ * VirtualBox version detection (OSE vs. regular)
16
+
17
+
18
+ ## Dependencies
19
+
20
+ The gem uses the VirtualBox CLI (command-line tools), so they must be installed
21
+ and on the system's path. The gem is developed against the documentation for
22
+ VirtualBox 4.
23
+
24
+ ## Development Dependencies
25
+
26
+ Running tests relies on a few command-line tools.
27
+
28
+ On Fedora, use the following command to install the packages.
29
+
30
+ ```bash
31
+ sudo yum install advancecomp curl mkisofs p7zip squashfs-tools
32
+ ```
33
+
34
+ On OSX, run the following command.
35
+
36
+ ```bash
37
+ brew install advancecomp cdrtools curl p7zip squashfs
38
+ ```
39
+
40
+
41
+ ## Limitations
42
+
43
+ This gem makes some simplifying assumptions (rails people would say it is
44
+ opinionated).
45
+
46
+ * VM configuration XML file management is completely delegated to VirtualBox;
47
+ the gem assumes and enforces the invariant that all XML files map to registered
48
+ VMs
49
+
50
+
51
+ ## Contributing to virtual_box
52
+
53
+ * Check out the latest master to make sure the feature hasn't been implemented
54
+ or the bug hasn't been fixed yet.
55
+ * Check out the issue tracker to make sure someone already hasn't requested it
56
+ and/or contributed it.
57
+ * Fork the project.
58
+ * Start a feature/bugfix branch.
59
+ * Commit and push until you are happy with your contribution.
60
+ * Make sure to add tests for it. This is important so I don't break it in a
61
+ future version unintentionally.
62
+ * Please do not mess with the Rakefile, version, or history.
63
+
64
+
65
+ ## Copyright
66
+
67
+ Copyright (c) 2010-2012 Victor Costan. See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1,28 +1,41 @@
1
- # Rakefile that uses echoe to manage virtual_box's gemspec.
2
- #
3
- # Author:: Victor Costan
4
- # Copyright:: Copyright (C) 2009 Zergling.Net
5
- # License:: MIT
1
+ # encoding: utf-8
6
2
 
7
3
  require 'rubygems'
8
- require 'echoe'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
9
13
 
10
- Echoe.new('virtual_box') do |p|
11
- p.project = 'zerglings' # rubyforge project
12
-
13
- p.author = 'Victor Costan'
14
- p.email = 'victor@zergling.net'
15
- p.summary = "Ruby API for VirtualBox (Sun's OSS virtualization software)."
16
- p.url = 'http://github.com/costan/virtual_box'
17
- p.dependencies = []
18
- p.development_dependencies = ["echoe >=3.1.1", "flexmock >=0.8.6"]
19
-
20
- p.need_tar_gz = true
21
- p.need_zip = true
22
- p.rdoc_pattern = /^(lib|bin|tasks|ext)|^BUILD|^README|^CHANGELOG|^TODO|^LICENSE|^COPYING$/
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "virtual_box"
18
+ gem.homepage = "http://github.com/csail/police"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{VirtualBox driver}
21
+ gem.description = %Q{Drives the VirtualBox command-line to manage VMs}
22
+ gem.email = "victor@costan.us"
23
+ gem.authors = ["Victor Costan"]
24
+ # dependencies defined in Gemfile
23
25
  end
26
+ Jeweler::RubygemsDotOrgTasks.new
24
27
 
25
- if $0 == __FILE__
26
- Rake.application = Rake::Application.new
27
- Rake.application.run
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
28
33
  end
34
+
35
+ load './test/tasks/tinycore.rake'
36
+
37
+ task :test => :fixtures
38
+ task :default => :test
39
+
40
+ require 'yard'
41
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,287 @@
1
+ module VirtualBox
2
+
3
+ # Specification for a virtual machine's motherboard.
4
+ class Board
5
+ # The number of CPUs (cores) on this board.
6
+ # @return [Integer]
7
+ attr_accessor :cpus
8
+
9
+ # The amount of megabytes of RAM on this board.
10
+ # @return [Integer]
11
+ attr_accessor :ram
12
+ # The amount of megabytes of video RAM on this board's video card.
13
+ # @return [Integer]
14
+ attr_accessor :video_ram
15
+
16
+ # The UUID presented to the guest OS.
17
+ # @return [String]
18
+ attr_accessor :hardware_id
19
+
20
+ # The OS that will be running in the virtualized VM.
21
+ #
22
+ # Used to improve the virtualization performance.
23
+ # @return [Symbol]
24
+ attr_accessor :os
25
+
26
+ # Whether the VM supports PAE (36-bit address space).
27
+ # @return [Boolean]
28
+ attr_accessor :pae
29
+ # Whether the VM supports ACPI.
30
+ # @return [Boolean]
31
+ attr_accessor :acpi
32
+ # Whether the VM supports I/O APIC.
33
+ #
34
+ # This is necessary for 64-bit OSes, but makes the virtualization slower.
35
+ # @return [Boolean]
36
+ attr_accessor :io_apic
37
+
38
+ # Whether the VMM attempts to use hardware support (Intel VT-x or AMD-V).
39
+ #
40
+ # Hardware virtualization can increase VM performance, especially used in
41
+ # conjunction with the other hardware virtualization options. However, using
42
+ # hardware virtualization in conjunction with other hypervisors can crash the
43
+ # host machine.
44
+ # @return [Boolean]
45
+ attr_accessor :hardware_virtualization
46
+ # Whether the VMM uses hardware support for nested paging.
47
+ #
48
+ # The option is used only if hardware_virtualization is set.
49
+ # @return [Boolean]
50
+ attr_accessor :nested_paging
51
+ # Whether the VMM uses hardware support for tagged TLB (VPID).
52
+ #
53
+ # The option is used only if hardware_virtualization is set.
54
+ # @return [Boolean]
55
+ attr_accessor :tagged_tlb
56
+
57
+ # Whether the VM supports 3D acceleration.
58
+ #
59
+ # 3D acceleration will only work with the proper guest extensions.
60
+ # @return [Boolean]
61
+ attr_accessor :accelerate_3d
62
+
63
+ # Whether the BIOS logo will fade in when the board boots.
64
+ # @return [Boolean]
65
+ attr_accessor :bios_logo_fade_in
66
+ # Whether the BIOS logo will fade out when the board boots.
67
+ # @return [Boolean]
68
+ attr_accessor :bios_logo_fade_out
69
+ # The number of seconds to display the BIOS logo when the board boots.
70
+ # @return [Integer]
71
+ attr_accessor :bios_logo_display_time
72
+ # Whether the BIOS allows the user to temporarily override the boot VM device.
73
+ #
74
+ # If false, no override is allowed. Otherwise, the user can press F12 at
75
+ # boot time to select a boot device. The user gets a prompt at boot time if
76
+ # the value is true. If the value is :menu_only the user does not get a
77
+ # prompt, but can still press F12 to select a device.
78
+ # @return [Boolean, Symbol]
79
+ attr_accessor :bios_boot_menu
80
+ # Indicates the boot device search order for the VM's BIOS.
81
+ #
82
+ # This is an array that can contain the following symbols: :floppy+, :dvd,
83
+ # :disk, :net. Symbols should not be repeated.
84
+ # @return [Array<Symbol>]
85
+ attr_accessor :boot_order
86
+
87
+ # True if the motherboard includes an audio chipset.
88
+ # @return [Boolean]
89
+ attr_accessor :audio
90
+
91
+ # If +true+, EFI firmware will be used instead of BIOS, for booting.
92
+ #
93
+ # The VirtualBox documentation states that EFI booting is highly experimental,
94
+ # and should only be used to virtualize MacOS.
95
+ # @return [Boolean]
96
+ attr_accessor :efi
97
+
98
+ # Creates a new motherboard specification based on the given attributes.
99
+ #
100
+ # @param [Hash<Symbol, Object>] options ActiveRecord-style initial values for
101
+ # attributes; can be used together with Board#to_hash to save and restore
102
+ def initialize(options = {})
103
+ reset
104
+ options.each { |k, v| self.send :"#{k}=", v }
105
+ end
106
+
107
+ # Arguments to "VBoxManage modifyvm" describing the VM's general settings.
108
+ #
109
+ # @return [Array<String>] arguments that can be concatenated to a "VBoxManage
110
+ # modifyvm" command
111
+ def to_params
112
+ params = []
113
+ params.push '--cpus', cpus.to_s
114
+ params.push '--memory', ram.to_s
115
+ params.push '--vram', video_ram.to_s
116
+ params.push '--hardwareuuid', hardware_id
117
+ params.push '--ostype',
118
+ self.class.os_types[self.class.os_types[os.to_s]]
119
+
120
+ params.push '--pae', pae ? 'on' : 'off'
121
+ params.push '--acpi', acpi ? 'on' : 'off'
122
+ params.push '--ioapic', io_apic ? 'on' : 'off'
123
+
124
+ params.push '--hwvirtex', hardware_virtualization ? 'on' : 'off'
125
+ params.push '--nestedpaging',
126
+ (hardware_virtualization && nested_paging) ? 'on' : 'off'
127
+ params.push '--vtxvpid',
128
+ (hardware_virtualization && tagged_tlb) ? 'on' : 'off'
129
+
130
+ params.push '--firmware', efi ? 'efi' : 'bios'
131
+ params.push '--bioslogofadein', bios_logo_fade_in ? 'on' : 'off'
132
+ params.push '--bioslogofadeout', bios_logo_fade_out ? 'on' : 'off'
133
+ params.push '--bioslogodisplaytime', bios_logo_display_time.to_s
134
+
135
+ bios_boot_menu_str = case bios_boot_menu
136
+ when false
137
+ 'disabled'
138
+ when :menu_only
139
+ 'message'
140
+ else
141
+ 'messageandmenu'
142
+ end
143
+ params.push '--biosbootmenu', bios_boot_menu_str
144
+ unique_boot_order = boot_order.uniq
145
+ 1.upto(4) do |i|
146
+ device = unique_boot_order[i - 1]
147
+ params.push "--boot#{i}", (device ? device.to_s : 'none')
148
+ end
149
+
150
+ params.push '--audio', (audio ? 'null' : 'none')
151
+
152
+ params
153
+ end
154
+
155
+ # Parses "VBoxManage showvminfo --machinereadable" output into this instance.
156
+ #
157
+ # @param [Hash<String, String>] params the "VBoxManage showvminfo" output,
158
+ # parsed by Vm.parse_machine_readble
159
+ # @return [VirtualBox::Board] self, for easy call chaining
160
+ def from_params(params)
161
+ self.cpus = params['cpus'].to_i
162
+ self.ram = params['memory'].to_i
163
+ self.video_ram = params['vram'].to_i
164
+ self.hardware_id = params['hardwareuuid']
165
+ self.os = self.class.os_types[params['ostype']]
166
+
167
+ self.pae = params['pae'] == 'on'
168
+ self.acpi = params['acpi'] == 'on'
169
+ self.io_apic = params['io_apic'] == 'on'
170
+
171
+ self.hardware_virtualization = params['hwvirtex'] == 'on'
172
+ self.nested_paging = params['nestedpaging'] == 'on'
173
+ self.tagged_tlb = params['vtxvpid'] == 'on'
174
+
175
+ self.efi = params['firmware'] == 'efi'
176
+ self.bios_logo_fade_in = params['bioslogofadein'] == 'on'
177
+ self.bios_logo_fade_out = params['bioslogofadeout'] == 'on'
178
+ self.bios_logo_display_time = params['bioslogodisplaytime'].to_i
179
+
180
+ self.bios_boot_menu = case params['bootmenu']
181
+ when 'disabled'
182
+ false
183
+ when 'message'
184
+ :menu_only
185
+ else
186
+ true
187
+ end
188
+
189
+ self.boot_order = []
190
+ %w(boot1 boot2 boot3 boot4).each do |boot_key|
191
+ next unless params[boot_key] && params[boot_key] != 'none'
192
+ boot_order << params[boot_key].to_sym
193
+ end
194
+
195
+ self.audio = params['audio'] != 'none'
196
+
197
+ self
198
+ end
199
+
200
+ # Resets to default settings.
201
+ #
202
+ # The defaults are chosen somewhat arbitrarily by the gem's author.
203
+ # @return [VirtualBox::Board] self, for easy call chaining
204
+ def reset
205
+ self.cpus = 1
206
+ self.ram = 512
207
+ self.video_ram = 18
208
+ self.hardware_id = UUID.generate
209
+
210
+ self.os = :other
211
+ self.pae = false
212
+ self.acpi = true
213
+ self.io_apic = false
214
+
215
+ self.hardware_virtualization = true
216
+ self.nested_paging = true
217
+ self.tagged_tlb = true
218
+ self.accelerate_3d = false
219
+
220
+ self.efi = false
221
+ self.bios_logo_fade_in = false
222
+ self.bios_logo_fade_out = false
223
+ self.bios_logo_display_time = 0
224
+ self.bios_boot_menu = false
225
+
226
+ self.boot_order = [:disk, :net, :dvd]
227
+
228
+ self.audio = false
229
+ self
230
+ end
231
+
232
+ # Hash capturing this motherboard specification. Can be passed to Board#new.
233
+ #
234
+ # @return [Hash<Symbol, Object>] Ruby-friendly Hash that can be used to
235
+ # re-create this motherboard specification
236
+ def to_hash
237
+ { :cpus => cpus, :ram => ram, :video_ram => video_ram,
238
+ :hardware_id => hardware_id, :os => os, :pae => pae, :acpi => acpi,
239
+ :io_apic => io_apic, :hardware_virtualization => hardware_virtualization,
240
+ :nested_paging => nested_paging, :tagged_tlb => tagged_tlb,
241
+ :accelerate_3d => accelerate_3d, :efi => efi,
242
+ :bios_logo_fade_in => bios_logo_fade_in,
243
+ :bios_logo_fade_out => bios_logo_fade_out,
244
+ :bios_logo_display_time => bios_logo_display_time,
245
+ :bios_boot_menu => bios_boot_menu, :audio => audio }
246
+ end
247
+
248
+ # The OS types supported by the VirtualBox installation.
249
+ #
250
+ # @return [Hash<Symbol|String, String|Symbol>] mapping from
251
+ # programmer-friendly symbols (e.g. :linux26) to proper VirtualBox OS IDs,
252
+ # and from VirtualBox IDs and description strings to programmer-friendly
253
+ # symbols
254
+ def self.os_types
255
+ return @os_types if @os_types
256
+
257
+ @os_types = {}
258
+ list_os_types.each do |key, value|
259
+ os_id = key.downcase.to_sym
260
+ @os_types[key] = os_id
261
+ @os_types[key.downcase] = os_id
262
+ @os_types[value] = os_id
263
+ @os_types[os_id] = key
264
+ end
265
+ @os_types
266
+ end
267
+
268
+ # Queries VirtualBox for available OS types.
269
+ #
270
+ # @return [Hash<String, String> mapping from each VirtualBox OS type ID to its
271
+ # description
272
+ def self.list_os_types
273
+ result = VirtualBox.run_command ['VBoxManage', '--nologo', 'list',
274
+ '--long', 'ostypes']
275
+ if result.status != 0
276
+ raise 'Unexpected error code returned by VirtualBox'
277
+ end
278
+
279
+ types = result.output.split("\n\n").map do |os_info|
280
+ i = Hash[os_info.split("\n").map { |line| line.split(':').map(&:strip) }]
281
+ [i['ID'], i['Description']]
282
+ end
283
+ Hash[types]
284
+ end
285
+ end # class VirtualBox::Board
286
+
287
+ end # namespace VirtualBox
@@ -0,0 +1,20 @@
1
+ # Run code via the command-line interface.
2
+
3
+ require 'English'
4
+ require 'shellwords'
5
+
6
+ module VirtualBox
7
+
8
+ # Runs a command in a sub-shell, waiting until the command completes.
9
+ #
10
+ # @param [Array<String>] args the name and arguments for the command to be run
11
+ #
12
+ # @return [Hashie::Mash<Symbol, String>] hash with the following keys / methods:
13
+ # :status:: the command's exit status
14
+ # :output:: a string with the command's output
15
+ def self.run_command(args)
16
+ output = Kernel.`(Shellwords.shelljoin(args))
17
+ Hashie::Mash.new :status => $CHILD_STATUS.exitstatus, :output => output
18
+ end
19
+
20
+ end # namespace VirtualBox