virtualbox 0.4.1 → 0.4.2

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 (44) hide show
  1. data/Readme.md +9 -9
  2. data/VERSION +1 -1
  3. data/docs/GettingStarted.md +11 -11
  4. data/docs/WhatsNew.md +1 -1
  5. data/lib/virtualbox.rb +10 -1
  6. data/lib/virtualbox/abstract_model.rb +47 -29
  7. data/lib/virtualbox/abstract_model/attributable.rb +16 -16
  8. data/lib/virtualbox/abstract_model/dirty.rb +10 -10
  9. data/lib/virtualbox/abstract_model/relatable.rb +22 -22
  10. data/lib/virtualbox/abstract_model/validatable.rb +4 -4
  11. data/lib/virtualbox/attached_device.rb +23 -23
  12. data/lib/virtualbox/command.rb +9 -9
  13. data/lib/virtualbox/dvd.rb +7 -7
  14. data/lib/virtualbox/ext/subclass_listing.rb +1 -1
  15. data/lib/virtualbox/extra_data.rb +17 -17
  16. data/lib/virtualbox/forwarded_port.rb +23 -23
  17. data/lib/virtualbox/hard_drive.rb +27 -27
  18. data/lib/virtualbox/image.rb +25 -18
  19. data/lib/virtualbox/nic.rb +22 -22
  20. data/lib/virtualbox/proxies/collection.rb +4 -4
  21. data/lib/virtualbox/shared_folder.rb +25 -25
  22. data/lib/virtualbox/storage_controller.rb +16 -16
  23. data/lib/virtualbox/vm.rb +95 -42
  24. data/test/virtualbox/abstract_model/attributable_test.rb +28 -28
  25. data/test/virtualbox/abstract_model/dirty_test.rb +13 -13
  26. data/test/virtualbox/abstract_model/relatable_test.rb +36 -36
  27. data/test/virtualbox/abstract_model/validatable_test.rb +22 -22
  28. data/test/virtualbox/abstract_model_test.rb +46 -36
  29. data/test/virtualbox/attached_device_test.rb +47 -47
  30. data/test/virtualbox/command_test.rb +12 -12
  31. data/test/virtualbox/dvd_test.rb +15 -19
  32. data/test/virtualbox/ext/subclass_listing_test.rb +2 -2
  33. data/test/virtualbox/extra_data_test.rb +37 -37
  34. data/test/virtualbox/forwarded_port_test.rb +31 -31
  35. data/test/virtualbox/hard_drive_test.rb +40 -48
  36. data/test/virtualbox/image_test.rb +36 -33
  37. data/test/virtualbox/nic_test.rb +22 -22
  38. data/test/virtualbox/proxies/collection_test.rb +6 -6
  39. data/test/virtualbox/shared_folder_test.rb +36 -36
  40. data/test/virtualbox/storage_controller_test.rb +14 -14
  41. data/test/virtualbox/vm_test.rb +121 -70
  42. data/test/virtualbox_test.rb +19 -0
  43. data/virtualbox.gemspec +5 -3
  44. metadata +4 -2
@@ -3,10 +3,6 @@ require File.join(File.dirname(__FILE__), '..', 'test_helper')
3
3
  class VMTest < Test::Unit::TestCase
4
4
  setup do
5
5
  @raw = <<-showvminfo
6
- VirtualBox Command Line Management Interface Version 3.1.2
7
- (C) 2005-2009 Sun Microsystems, Inc.
8
- All rights reserved.
9
-
10
6
  name="foo"
11
7
  ostype="Ubuntu"
12
8
  UUID="8710d3db-d96a-46ed-9004-59fa891fda90"
@@ -77,13 +73,13 @@ SharedFolderPathMachineMapping1="/virtualbox"
77
73
  SharedFolderNameMachineMapping2="otherfolder"
78
74
  SharedFolderPathMachineMapping2="/virtualbox/lib"
79
75
  showvminfo
80
-
76
+
81
77
  @name = "foo"
82
-
78
+
83
79
  # Just to be sure nothing is executed
84
80
  VirtualBox::Command.stubs(:execute).returns('')
85
81
  end
86
-
82
+
87
83
  def create_vm
88
84
  VirtualBox::Command.expects(:vboxmanage).with("showvminfo #{@name} --machinereadable").returns(@raw)
89
85
  VirtualBox::Command.expects(:vboxmanage).with("showvminfo #{@name}").returns("")
@@ -94,65 +90,87 @@ showvminfo
94
90
  assert vm
95
91
  vm
96
92
  end
97
-
93
+
98
94
  context "human readable info" do
99
95
  should "not pass --machinereadable into the showvminfo command" do
100
96
  VirtualBox::Command.expects(:vboxmanage).with("showvminfo #{@name}").once
101
97
  VirtualBox::VM.human_info(@name)
102
98
  end
103
-
99
+
104
100
  should "shell escape parameter" do
105
101
  VirtualBox::Command.expects(:vboxmanage).with("showvminfo hello\\ world").once
106
102
  VirtualBox::VM.human_info("hello world")
107
103
  end
108
104
  end
109
-
105
+
110
106
  context "reading the VM state" do
111
107
  setup do
112
108
  @vm = create_vm
113
109
  end
114
-
110
+
115
111
  should "read the initial state when loading the VM" do
116
112
  assert_equal "poweroff", @vm.state
117
113
  end
118
-
114
+
119
115
  should "reload the state if true is passed as a parameter" do
120
116
  VirtualBox::VM.expects(:raw_info).returns({ :vmstate => "on" })
121
117
  assert_equal "on", @vm.state(true)
122
118
  assert_equal "on", @vm.state
123
119
  end
120
+
121
+ should "provide conveniance methods for determining VM state" do
122
+ VirtualBox::VM.expects(:raw_info).returns({ :vmstate => "poweroff" })
123
+ assert_equal "poweroff", @vm.state(true)
124
+ assert @vm.powered_off?
125
+
126
+ VirtualBox::VM.expects(:raw_info).returns({ :vmstate => "running" })
127
+ assert_equal "running", @vm.state(true)
128
+ assert @vm.running?
129
+
130
+ VirtualBox::VM.expects(:raw_info).returns({ :vmstate => "paused" })
131
+ assert_equal "paused", @vm.state(true)
132
+ assert @vm.paused?
133
+
134
+ VirtualBox::VM.expects(:raw_info).returns({ :vmstate => "saved" })
135
+ assert_equal "saved", @vm.state(true)
136
+ assert @vm.saved?
137
+
138
+ VirtualBox::VM.expects(:raw_info).returns({ :vmstate => "aborted" })
139
+ assert_equal "aborted", @vm.state(true)
140
+ assert @vm.aborted?
141
+ end
124
142
  end
125
-
143
+
126
144
  context "exporting a VM" do
127
145
  setup do
128
146
  @vm = create_vm
129
147
  end
130
-
148
+
131
149
  should "export the VM with no options if none are passed" do
132
150
  VirtualBox::Command.expects(:vboxmanage).with("export #{@name} -o foo")
133
151
  @vm.export("foo")
134
152
  end
135
-
153
+
136
154
  should "export the VM with specified options" do
137
155
  VirtualBox::Command.expects(:vboxmanage).with("export #{@name} -o foo --vsys 0 --foo bar")
138
156
  @vm.export("foo", :foo => :bar)
139
157
  end
140
-
158
+
141
159
  should "shell escape all the options" do
142
160
  VirtualBox::Command.expects(:vboxmanage).with("export #{@name} -o foo --vsys 0 --foo a\\ space")
143
161
  @vm.export("foo", :foo => "a space")
144
162
  end
145
-
163
+
146
164
  should "return true if the export succeeded" do
147
165
  VirtualBox::Command.expects(:vboxmanage).once
148
166
  assert @vm.export("foo")
149
167
  end
150
-
168
+
151
169
  should "return false if the export failed" do
152
170
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
153
171
  assert !@vm.export("foo")
154
172
  end
155
-
173
+
156
174
  should "raise an exception on failure if raise_error is true" do
157
175
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
158
176
  assert_raises(VirtualBox::Exceptions::CommandFailedException) {
@@ -160,23 +178,29 @@ showvminfo
160
178
  }
161
179
  end
162
180
  end
163
-
181
+
164
182
  context "controlling a VM (start, stop, pause, etc.)" do
165
183
  setup do
166
184
  @vm = create_vm
167
185
  end
168
-
186
+
169
187
  context "control method" do
188
+ should "shell escape the vm name" do
189
+ VirtualBox::Command.expects(:vboxmanage).with("controlvm hello\\ world FOO")
190
+ @vm.instance_variable_set(:@original_name, "hello world")
191
+ assert @vm.control(:FOO)
192
+ end
193
+
170
194
  should "run the given command when 'control' is called" do
171
195
  VirtualBox::Command.expects(:vboxmanage).with("controlvm #{@name} foo")
172
196
  assert @vm.control(:foo)
173
197
  end
174
-
198
+
175
199
  should "return false if the command failed" do
176
200
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
177
201
  assert !@vm.control(:foo)
178
202
  end
179
-
203
+
180
204
  should "raise an exception if flag is set" do
181
205
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
182
206
  assert_raises(VirtualBox::Exceptions::CommandFailedException) {
@@ -184,50 +208,68 @@ showvminfo
184
208
  }
185
209
  end
186
210
  end
187
-
211
+
188
212
  should "start a VM with the given type" do
189
213
  VirtualBox::Command.expects(:vboxmanage).with("startvm #{@name} --type FOO")
190
214
  assert @vm.start(:FOO)
191
215
  end
192
-
216
+
193
217
  should "return false if start failed" do
194
218
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
195
219
  assert !@vm.start
196
220
  end
197
-
221
+
222
+ should "shell escape the VM name on start" do
223
+ VirtualBox::Command.expects(:vboxmanage).with("startvm hello\\ world --type FOO")
224
+ @vm.instance_variable_set(:@original_name, "hello world")
225
+ assert @vm.start(:FOO)
226
+ end
227
+
198
228
  should "raise an exception if start fails and flag is set" do
199
229
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
200
230
  assert_raises(VirtualBox::Exceptions::CommandFailedException) {
201
231
  @vm.start(:foo, true)
202
232
  }
203
233
  end
204
-
234
+
235
+ should "stop a VM with a 'poweroff'" do
236
+ @vm.expects(:control).with(:acpipowerbutton, false).returns(true)
237
+ assert @vm.shutdown
238
+ end
239
+
205
240
  should "stop a VM with a 'poweroff'" do
206
241
  @vm.expects(:control).with(:poweroff, false).returns(true)
207
242
  assert @vm.stop
208
243
  end
209
-
244
+
210
245
  should "pause a VM" do
211
246
  @vm.expects(:control).with(:pause, false).returns(true)
212
247
  assert @vm.pause
213
248
  end
214
-
249
+
215
250
  should "resume a VM" do
216
251
  @vm.expects(:control).with(:resume, false).returns(true)
217
252
  assert @vm.resume
218
253
  end
219
-
254
+
220
255
  should "save the state of a VM" do
221
256
  @vm.expects(:control).with(:savestate, false).returns(true)
222
257
  assert @vm.save_state
223
258
  end
224
259
  end
225
-
260
+
226
261
  context "destroying" do
227
262
  setup do
228
263
  @vm = create_vm
229
264
  end
230
265
 
266
+ should "shell escape the name" do
267
+ VirtualBox::StorageController.expects(:destroy_relationship)
268
+ VirtualBox::Command.expects(:vboxmanage).with("unregistervm hello\\ world --delete")
269
+ @vm.instance_variable_set(:@original_name, "hello world")
270
+ @vm.destroy
271
+ end
272
+
231
273
  should "destroy all storage controllers before destroying VM" do
232
274
  destroy_seq = sequence("destroy_seq")
233
275
  VirtualBox::StorageController.expects(:destroy_relationship).in_sequence(destroy_seq)
@@ -235,7 +277,7 @@ showvminfo
235
277
  @vm.destroy
236
278
  end
237
279
  end
238
-
280
+
239
281
  context "finding all VMs" do
240
282
  setup do
241
283
  @raw = <<-raw
@@ -243,26 +285,26 @@ showvminfo
243
285
  "bar" {zefaldf}
244
286
  raw
245
287
  end
246
-
288
+
247
289
  should "list VMs then parse them" do
248
290
  all_seq = sequence("all")
249
291
  VirtualBox::Command.expects(:vboxmanage).with("list vms").returns(@raw).in_sequence(all_seq)
250
292
  VirtualBox::VM.expects(:parse_vm_list).with(@raw).in_sequence(all_seq)
251
293
  VirtualBox::VM.all
252
294
  end
253
-
295
+
254
296
  context "parser" do
255
297
  should "ignore non-matching lines" do
256
298
  assert VirtualBox::VM.parse_vm_list("HEY YOU").empty?
257
299
  end
258
-
300
+
259
301
  should "return VM objects for valid lines" do
260
302
  vm_foo = mock("vm_foo")
261
303
  vm_bar = mock("vm_bar")
262
304
  parse_seq = sequence("parse")
263
305
  VirtualBox::VM.expects(:find).with("foo").returns(vm_foo).in_sequence(parse_seq)
264
306
  VirtualBox::VM.expects(:find).with("bar").returns(vm_bar).in_sequence(parse_seq)
265
-
307
+
266
308
  result = VirtualBox::VM.parse_vm_list(@raw)
267
309
  assert !result.empty?
268
310
  assert_equal 2, result.length
@@ -271,14 +313,10 @@ raw
271
313
  end
272
314
  end
273
315
  end
274
-
316
+
275
317
  context "importing a VM" do
276
318
  setup do
277
319
  @raw = <<-raw
278
- VirtualBox Command Line Management Interface Version 3.1.2
279
- (C) 2005-2009 Sun Microsystems, Inc.
280
- All rights reserved.
281
-
282
320
  0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
283
321
  Interpreting /Users/mitchellh/base.ovf...
284
322
  OK.
@@ -288,79 +326,87 @@ Virtual system 0:
288
326
  (change with "--vsys 0 --ostype <type>"; use "list ostypes" to list all possible values)
289
327
  1: Suggested VM name "Base_1"
290
328
  (change with "--vsys 0 --vmname <name>")
291
- 2: Number of CPUs: 1
329
+ 2: Number of CPUs: 1
292
330
  raw
293
331
  end
294
-
332
+
295
333
  should "attempt to find the imported VM" do
296
334
  VirtualBox::Command.expects(:vboxmanage).with("import whatever").returns(@raw)
297
335
  VirtualBox::VM.expects(:find).with("Base_1").once
298
336
  VirtualBox::VM.import("whatever")
299
337
  end
300
338
 
301
- should "parse the VM name from the raw string" do
339
+ should "parse the VM name from the raw string" do
302
340
  assert_equal "Base_1", VirtualBox::VM.parse_vm_name(@raw)
303
341
  end
304
-
342
+
305
343
  should "return nil on parsing the VM name if its invalid" do
306
344
  assert_nil VirtualBox::VM.parse_vm_name("Name foo")
307
345
  end
308
346
  end
309
-
347
+
310
348
  context "saving a changed VM" do
311
349
  setup do
312
350
  @vm = create_vm
313
351
  VirtualBox::AttachedDevice.any_instance.stubs(:save)
314
352
  end
315
-
353
+
316
354
  should "return false if saving fails" do
317
355
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
318
-
356
+
319
357
  @vm.ostype = "Zubuntu"
320
358
  assert !@vm.save
321
359
  end
322
-
360
+
323
361
  should "raise an error if saving fails and flag to true" do
324
362
  VirtualBox::Command.stubs(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
325
-
363
+
326
364
  @vm.ostype = "Zubuntu"
327
365
  assert_raises(VirtualBox::Exceptions::CommandFailedException) {
328
366
  @vm.save(true)
329
367
  }
330
368
  end
331
-
369
+
332
370
  should "save only the attributes which saved" do
333
371
  VirtualBox::Command.expects(:vboxmanage).with("modifyvm #{@name} --ostype Zubuntu")
334
-
372
+
335
373
  @vm.ostype = "Zubuntu"
336
374
  assert @vm.save
337
375
  end
338
-
376
+
339
377
  should "shell escape saved values" do
340
378
  VirtualBox::Command.expects(:vboxmanage).with("modifyvm #{@name} --ostype My\\ Value")
341
-
379
+
342
380
  @vm.ostype = "My Value"
343
381
  assert @vm.save
344
382
  end
345
-
383
+
346
384
  should "shell escape the string value of a value" do
347
385
  VirtualBox::Command.expects(:vboxmanage).with("modifyvm #{@name} --memory 400")
348
-
386
+
349
387
  @vm.memory = 400
350
388
  assert_nothing_raised { @vm.save }
351
389
  end
352
-
390
+
391
+ should "shell escape the VM name when saving an attribute" do
392
+ VirtualBox::Command.expects(:vboxmanage).with("modifyvm hello\\ world --memory 400")
393
+
394
+ @vm.memory = 400
395
+ @vm.instance_variable_set(:@original_name, "hello world")
396
+ assert @vm.save
397
+ end
398
+
353
399
  should "save name first if changed, then following values should modify new VM" do
354
400
  save_seq = sequence("save_seq")
355
401
  new_name = "foo2"
356
402
  VirtualBox::Command.expects(:vboxmanage).with("modifyvm #{@name} --name #{new_name}").in_sequence(save_seq)
357
403
  VirtualBox::Command.expects(:vboxmanage).with("modifyvm #{new_name} --ostype Zubuntu").in_sequence(save_seq)
358
-
404
+
359
405
  @vm.name = new_name
360
406
  @vm.ostype = "Zubuntu"
361
407
  assert @vm.save
362
408
  end
363
-
409
+
364
410
  should "save the relationships as well" do
365
411
  VirtualBox::Nic.expects(:save_relationship).once
366
412
  VirtualBox::StorageController.expects(:save_relationship).once
@@ -370,7 +416,7 @@ raw
370
416
  assert @vm.save
371
417
  end
372
418
  end
373
-
419
+
374
420
  context "finding a VM by name" do
375
421
  setup do
376
422
 
@@ -379,57 +425,62 @@ raw
379
425
  :ostype => "Ubuntu",
380
426
  :uuid => "8710d3db-d96a-46ed-9004-59fa891fda90"
381
427
  }
382
-
428
+
383
429
  command_seq = sequence("command_seq)")
384
430
  VirtualBox::Command.expects(:vboxmanage).with("showvminfo #{@name} --machinereadable").returns(@raw).in_sequence(command_seq)
385
431
  VirtualBox::Command.expects(:vboxmanage).with(anything).returns("").at_least(0).in_sequence(command_seq)
386
432
  @vm = VirtualBox::VM.find(@name)
387
433
  assert @vm
388
434
  end
389
-
435
+
390
436
  should "shell escape the VM name" do
391
437
  VirtualBox::Command.expects(:vboxmanage).with("showvminfo hello\\ world --machinereadable").returns(@raw)
392
438
  assert VirtualBox::VM.find("hello world")
393
439
  end
394
-
395
- should "return a VM object with proper attributes" do
440
+
441
+ should "return a VM object with proper attributes" do
396
442
  @expected.each do |k,v|
397
443
  assert_equal v, @vm.read_attribute(k)
398
444
  end
399
445
  end
400
-
446
+
447
+ should "return nil if the VM doesn't exist" do
448
+ VirtualBox::Command.expects(:vboxmanage).raises(VirtualBox::Exceptions::CommandFailedException)
449
+ assert_nil VirtualBox::VM.find("dont exist")
450
+ end
451
+
401
452
  should "properly load nic relationship" do
402
453
  assert @vm.nics
403
454
  assert @vm.nics.is_a?(Array)
404
455
  assert_equal 8, @vm.nics.length
405
456
  end
406
-
457
+
407
458
  should "properly load storage controller relationship" do
408
459
  assert @vm.storage_controllers
409
460
  assert @vm.storage_controllers.is_a?(Array)
410
461
  assert_equal 2, @vm.storage_controllers.length
411
462
  end
412
-
463
+
413
464
  should "properly load shared folder relationship" do
414
465
  assert @vm.shared_folders
415
466
  assert @vm.shared_folders.is_a?(Array)
416
467
  assert_equal 2, @vm.shared_folders.length
417
468
  end
418
469
  end
419
-
470
+
420
471
  context "parsing the showvminfo output" do
421
472
  should "lowercase and symbolize the keys" do
422
473
  result = VirtualBox::VM.parse_vm_info("ZING=Zam")
423
474
  assert_equal 1, result.length
424
475
  assert_equal "Zam", result[:zing]
425
476
  end
426
-
477
+
427
478
  should "ignore quotes for multi-word keys or values" do
428
479
  result = VirtualBox::VM.parse_vm_info('"foo bar"="baz"')
429
480
  assert_equal 1, result.length
430
481
  assert_equal "baz", result[:"foo bar"]
431
482
  end
432
-
483
+
433
484
  should "ignore the lines which aren't the proper format" do
434
485
  result = VirtualBox::VM.parse_vm_info(<<-block)
435
486
  This should not be parsed