virtualbox 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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