fission 0.3.0 → 0.4.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +1 -0
  2. data/CHANGELOG.md +3 -0
  3. data/README.md +1 -1
  4. data/lib/fission.rb +5 -6
  5. data/lib/fission/cli.rb +77 -7
  6. data/lib/fission/command.rb +43 -1
  7. data/lib/fission/command/clone.rb +19 -20
  8. data/lib/fission/command/delete.rb +29 -25
  9. data/lib/fission/command/snapshot_create.rb +11 -26
  10. data/lib/fission/command/snapshot_list.rb +13 -19
  11. data/lib/fission/command/snapshot_revert.rb +11 -26
  12. data/lib/fission/command/start.rb +11 -25
  13. data/lib/fission/command/status.rb +26 -10
  14. data/lib/fission/command/stop.rb +10 -21
  15. data/lib/fission/command/suspend.rb +21 -21
  16. data/lib/fission/command_helpers.rb +21 -0
  17. data/lib/fission/config.rb +35 -0
  18. data/lib/fission/fusion.rb +11 -3
  19. data/lib/fission/lease.rb +148 -0
  20. data/lib/fission/metadata.rb +55 -2
  21. data/lib/fission/response.rb +76 -0
  22. data/lib/fission/ui.rb +49 -0
  23. data/lib/fission/version.rb +1 -1
  24. data/lib/fission/vm.rb +653 -75
  25. data/spec/contexts/command.rb +12 -0
  26. data/spec/fission/cli_spec.rb +4 -11
  27. data/spec/fission/command/clone_spec.rb +45 -45
  28. data/spec/fission/command/delete_spec.rb +56 -43
  29. data/spec/fission/command/snapshot_create_spec.rb +29 -51
  30. data/spec/fission/command/snapshot_list_spec.rb +25 -26
  31. data/spec/fission/command/snapshot_revert_spec.rb +27 -53
  32. data/spec/fission/command/start_spec.rb +25 -69
  33. data/spec/fission/command/status_spec.rb +48 -13
  34. data/spec/fission/command/stop_spec.rb +25 -42
  35. data/spec/fission/command/suspend_spec.rb +54 -49
  36. data/spec/fission/command_helpers_spec.rb +30 -0
  37. data/spec/fission/command_spec.rb +19 -0
  38. data/spec/fission/config_spec.rb +24 -0
  39. data/spec/fission/fusion_spec.rb +6 -6
  40. data/spec/fission/lease_spec.rb +176 -0
  41. data/spec/fission/metadata_spec.rb +8 -8
  42. data/spec/fission/response_spec.rb +81 -0
  43. data/spec/fission/vm_spec.rb +869 -193
  44. data/spec/fission_spec.rb +0 -6
  45. data/spec/helpers/command_helpers.rb +12 -0
  46. data/spec/helpers/response_helpers.rb +21 -0
  47. data/spec/matchers/be_a_successful_response.rb +7 -0
  48. data/spec/matchers/be_an_unsuccessful_response.rb +10 -0
  49. data/spec/spec_helper.rb +7 -0
  50. metadata +24 -5
@@ -0,0 +1,81 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Response do
4
+ describe 'initialize' do
5
+ it 'should allow you to set the code' do
6
+ Fission::Response.new(:code => 1).code.should == 1
7
+ end
8
+
9
+ it 'should set the code to 1 if not provided' do
10
+ Fission::Response.new.code.should == 1
11
+ end
12
+
13
+ it 'should allow you to set the message' do
14
+ Fission::Response.new(:message => 'foobar').message.should == 'foobar'
15
+ end
16
+
17
+ it 'should set the message to an empty string if not provided' do
18
+ Fission::Response.new.message.should == ''
19
+ end
20
+
21
+ it 'should set the data to nil if not provided' do
22
+ Fission::Response.new.data.should be_nil
23
+ end
24
+
25
+ end
26
+
27
+ describe 'code' do
28
+ it 'should allow you to set the code' do
29
+ @response = Fission::Response.new
30
+ @response.code = 4
31
+ @response.code.should == 4
32
+ end
33
+ end
34
+
35
+ describe 'successful?' do
36
+ it 'should return true if the code is 0' do
37
+ Fission::Response.new(:code => 0).successful?.should == true
38
+ end
39
+
40
+ it 'should return false if the code is not 0' do
41
+ Fission::Response.new(:code => 1).successful?.should == false
42
+ end
43
+ end
44
+
45
+ describe 'message' do
46
+ it 'should allow you to set the message' do
47
+ @response = Fission::Response.new
48
+ @response.message = 'foobar'
49
+ @response.message.should == 'foobar'
50
+ end
51
+ end
52
+
53
+ describe 'data' do
54
+ it 'should allow you to set the data' do
55
+ @response = Fission::Response.new
56
+ @response.data = [1, 2, 3]
57
+ @response.data.should == [1, 2, 3]
58
+ end
59
+ end
60
+
61
+ describe 'self.from_command' do
62
+ it 'should return a response object' do
63
+ Fission::Response.from_command('').should be_a Fission::Response
64
+ end
65
+
66
+ it 'should set the code to the exit status' do
67
+ $?.should_receive(:exitstatus).and_return(55)
68
+ Fission::Response.from_command('').code.should == 55
69
+ end
70
+
71
+ it 'should set the message if the command was unsuccessful' do
72
+ $?.should_receive(:exitstatus).and_return(55)
73
+ Fission::Response.from_command('foo').message.should == 'foo'
74
+ end
75
+ it 'should not set the message if the command was successful' do
76
+ $?.should_receive(:exitstatus).and_return(0)
77
+ Fission::Response.from_command('foo').message.should == ''
78
+ end
79
+
80
+ end
81
+ end
@@ -2,11 +2,11 @@ require File.expand_path('../../spec_helper.rb', __FILE__)
2
2
 
3
3
  describe Fission::VM do
4
4
  before do
5
- @string_io = StringIO.new
6
- Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
7
5
  @vm = Fission::VM.new('foo')
8
- @vm.stub!(:conf_file).and_return(File.join(Fission::VM.path('foo'), 'foo.vmx'))
9
- @vmrun_cmd = Fission.config.attributes['vmrun_cmd']
6
+ @vm.stub!(:conf_file).and_return(File.join(@vm.path, 'foo.vmx'))
7
+ @conf_file_path = File.join(@vm.path, 'foo.vmx')
8
+ @vmrun_cmd = Fission.config['vmrun_cmd']
9
+ @conf_file_response_mock = mock('conf_file_response')
10
10
  end
11
11
 
12
12
  describe 'new' do
@@ -16,148 +16,724 @@ describe Fission::VM do
16
16
  end
17
17
 
18
18
  describe 'start' do
19
- it 'should output that it was successful' do
20
- $?.should_receive(:exitstatus).and_return(0)
21
- @vm.should_receive(:`).
22
- with("#{@vmrun_cmd} start #{@vm.conf_file.gsub(' ', '\ ')} gui 2>&1").
23
- and_return("it's all good")
24
- @vm.start
19
+ before do
20
+ @running_response_mock = mock('running?')
25
21
 
26
- @string_io.string.should match /VM started/
22
+ @vm.stub(:exists?).and_return(true)
23
+ @vm.stub(:running?).and_return(@running_response_mock)
24
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
25
+ @running_response_mock.stub_as_successful false
26
+ @conf_file_response_mock.stub_as_successful @conf_file_path
27
27
  end
28
28
 
29
- it 'should start the vm headless' do
30
- $?.should_receive(:exitstatus).and_return(0)
31
- @vm.should_receive(:`).
32
- with("#{@vmrun_cmd} start #{@vm.conf_file.gsub(' ', '\ ')} nogui 2>&1").
33
- and_return("it's all good")
34
- @vm.start(:headless => true)
29
+ it "should return an unsuccessful response if the vm doesn't exist" do
30
+ @vm.stub(:exists?).and_return(false)
31
+ @vm.start.should be_an_unsuccessful_response 'VM does not exist'
32
+ end
35
33
 
36
- @string_io.string.should match /VM started/
34
+ it 'should return an unsuccessful response if the vm is already running' do
35
+ @running_response_mock.stub_as_successful true
36
+ @vm.start.should be_an_unsuccessful_response 'VM is already running'
37
37
  end
38
38
 
39
- it 'should output that it was unsuccessful' do
40
- $?.should_receive(:exitstatus).and_return(1)
41
- @vm.should_receive(:`).
42
- with("#{@vmrun_cmd} start #{@vm.conf_file.gsub(' ', '\ ')} gui 2>&1").
43
- and_return("it blew up")
44
- @vm.start
39
+ it 'should return an unsuccessful response if unable to determine if running' do
40
+ @running_response_mock.stub_as_unsuccessful
41
+ @vm.start.should be_an_unsuccessful_response
42
+ end
45
43
 
46
- @string_io.string.should match /There was a problem starting the VM.+it blew up.+/m
44
+ it 'should return an unsuccessful response if unable to figure out the conf file' do
45
+ @conf_file_response_mock.stub_as_unsuccessful
46
+ @vm.start.should be_an_unsuccessful_response
47
+ end
48
+
49
+ describe 'when the fusion gui is not running' do
50
+ before do
51
+ Fission::Fusion.stub(:running?).and_return(false)
52
+ end
53
+
54
+ it 'should start the VM and return a successful response' do
55
+ $?.should_receive(:exitstatus).and_return(0)
56
+ @vm.should_receive(:`).
57
+ with("#{@vmrun_cmd} start #{@conf_file_path.gsub(' ', '\ ')} gui 2>&1").
58
+ and_return("it's all good")
59
+
60
+ @vm.start.should be_a_successful_response
61
+ end
62
+
63
+ it 'should successfully start the vm headless' do
64
+ $?.should_receive(:exitstatus).and_return(0)
65
+ @vm.should_receive(:`).
66
+ with("#{@vmrun_cmd} start #{@conf_file_path.gsub(' ', '\ ')} nogui 2>&1").
67
+ and_return("it's all good")
68
+
69
+ @vm.start(:headless => true).should be_a_successful_response
70
+ end
71
+
72
+ it 'should return an unsuccessful response if there was an error starting the VM' do
73
+ $?.should_receive(:exitstatus).and_return(1)
74
+ @vm.should_receive(:`).
75
+ with("#{@vmrun_cmd} start #{@conf_file_path.gsub(' ', '\ ')} gui 2>&1").
76
+ and_return("it blew up")
77
+
78
+ @vm.start.should be_an_unsuccessful_response
79
+ end
80
+ end
81
+
82
+ describe 'when the fusion gui is running' do
83
+ before do
84
+ Fission::Fusion.stub(:running?).and_return(true)
85
+ end
86
+
87
+ it 'should return an unsuccessful response if starting headless' do
88
+ response = @vm.start :headless => true
89
+
90
+ error_string = 'It looks like the Fusion GUI is currently running. '
91
+ error_string << 'A VM cannot be started in headless mode when the Fusion GUI is running. '
92
+ error_string << 'Exit the Fusion GUI and try again.'
93
+
94
+ response.should be_an_unsuccessful_response error_string
95
+ end
47
96
  end
48
97
 
49
98
  end
50
99
 
51
100
  describe 'stop' do
52
- it 'should output that it was successful' do
101
+ before do
102
+ @running_response_mock = mock('running?')
103
+
104
+ @vm.stub(:exists?).and_return(true)
105
+ @vm.stub(:running?).and_return(@running_response_mock)
106
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
107
+ @running_response_mock.stub_as_successful true
108
+ @conf_file_response_mock.stub_as_successful @conf_file_path
109
+ end
110
+
111
+ it "should return an unsuccessful response if the vm doesn't exist" do
112
+ @vm.stub(:exists?).and_return(false)
113
+ @vm.stop.should be_an_unsuccessful_response 'VM does not exist'
114
+ end
115
+
116
+ it 'should return an unsuccessful response if the vm is not running' do
117
+ @running_response_mock.stub_as_successful false
118
+ @vm.stop.should be_an_unsuccessful_response 'VM is not running'
119
+ end
120
+
121
+ it 'should return an unsuccessful response if unable to determine if running' do
122
+ @running_response_mock.stub_as_unsuccessful
123
+ @vm.stop.should be_an_unsuccessful_response
124
+ end
125
+
126
+ it 'should return an unsuccessful response if unable to figure out the conf file' do
127
+ @conf_file_response_mock.stub_as_unsuccessful
128
+ @vm.stop.should be_an_unsuccessful_response
129
+ end
130
+
131
+ it 'should return a successful response and stop the vm' do
132
+ $?.should_receive(:exitstatus).and_return(0)
133
+ @vm.should_receive(:`).
134
+ with("#{@vmrun_cmd} stop #{@conf_file_path.gsub ' ', '\ '} 2>&1").
135
+ and_return("it's all good")
136
+
137
+ @vm.stop.should be_a_successful_response
138
+ end
139
+
140
+ it 'should return a suscessful response and hard stop the vm' do
53
141
  $?.should_receive(:exitstatus).and_return(0)
54
142
  @vm.should_receive(:`).
55
- with("#{@vmrun_cmd} stop #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
143
+ with("#{@vmrun_cmd} stop #{@conf_file_path.gsub ' ', '\ '} hard 2>&1").
56
144
  and_return("it's all good")
57
- @vm.stop
58
145
 
59
- @string_io.string.should match /VM stopped/
146
+ @vm.stop(:hard => true).should be_a_successful_response
60
147
  end
61
148
 
62
- it 'it should output that it was unsuccessful' do
149
+ it 'it should return an unsuccessful response if unable to stop the vm' do
63
150
  $?.should_receive(:exitstatus).and_return(1)
64
151
  @vm.should_receive(:`).
65
- with("#{@vmrun_cmd} stop #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
152
+ with("#{@vmrun_cmd} stop #{@conf_file_path.gsub ' ', '\ '} 2>&1").
66
153
  and_return("it blew up")
67
- @vm.stop
68
154
 
69
- @string_io.string.should match /There was a problem stopping the VM.+it blew up.+/m
155
+ @vm.stop.should be_an_unsuccessful_response
70
156
  end
71
157
  end
72
158
 
73
159
  describe 'suspend' do
74
- it 'should output that it was successful' do
160
+ before do
161
+ @running_response_mock = mock('running?')
162
+
163
+ @vm.stub(:exists?).and_return(true)
164
+ @vm.stub(:running?).and_return(@running_response_mock)
165
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
166
+ @running_response_mock.stub_as_successful true
167
+ @conf_file_response_mock.stub_as_successful @conf_file_path
168
+ end
169
+
170
+ it "should return an unsuccessful response if the vm doesn't exist" do
171
+ @vm.stub(:exists?).and_return(false)
172
+ @vm.suspend.should be_an_unsuccessful_response 'VM does not exist'
173
+ end
174
+
175
+ it 'should return an unsuccessful response if the vm is not running' do
176
+ @running_response_mock.stub_as_successful false
177
+ @vm.suspend.should be_an_unsuccessful_response 'VM is not running'
178
+ end
179
+
180
+ it 'should return an unsuccessful response if unable to determine if running' do
181
+ @running_response_mock.stub_as_unsuccessful
182
+ @vm.suspend.should be_an_unsuccessful_response
183
+ end
184
+
185
+ it 'should return an unsuccessful response if unable to figure out the conf file' do
186
+ @conf_file_response_mock.stub_as_unsuccessful
187
+ @vm.suspend.should be_an_unsuccessful_response
188
+ end
189
+
190
+ it 'should return a successful response' do
75
191
  $?.should_receive(:exitstatus).and_return(0)
76
192
  @vm.should_receive(:`).
77
- with("#{@vmrun_cmd} suspend #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
193
+ with("#{@vmrun_cmd} suspend #{@conf_file_path.gsub ' ', '\ '} 2>&1").
78
194
  and_return("it's all good")
79
- @vm.suspend
80
195
 
81
- @string_io.string.should match /VM suspended/
196
+ @vm.suspend.should be_a_successful_response
82
197
  end
83
198
 
84
- it 'it should output that it was unsuccessful' do
199
+ it 'it should return an unsuccessful response if unable to suspend the vm' do
85
200
  $?.should_receive(:exitstatus).and_return(1)
86
201
  @vm.should_receive(:`).
87
- with("#{@vmrun_cmd} suspend #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
202
+ with("#{@vmrun_cmd} suspend #{@conf_file_path.gsub ' ', '\ '} 2>&1").
88
203
  and_return("it blew up")
89
- @vm.suspend
90
204
 
91
- @string_io.string.should match /There was a problem suspending the VM.+it blew up.+/m
205
+ @vm.suspend.should be_an_unsuccessful_response
92
206
  end
93
207
  end
94
208
 
95
209
  describe 'snapshots' do
96
- it 'should return the list of snapshots' do
210
+ before do
211
+ @vm.stub(:exists?).and_return(true)
212
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
213
+ @conf_file_response_mock.stub_as_successful @conf_file_path
214
+ end
215
+
216
+ it "should return an unsuccessful repsonse when the vm doesn't exist" do
217
+ @vm.stub(:exists?).and_return(false)
218
+ @vm.snapshots.should be_an_unsuccessful_response 'VM does not exist'
219
+ end
220
+
221
+ it 'should return a successful response with the list of snapshots' do
97
222
  $?.should_receive(:exitstatus).and_return(0)
98
223
  @vm.should_receive(:`).
99
- with("#{@vmrun_cmd} listSnapshots #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
224
+ with("#{@vmrun_cmd} listSnapshots #{@conf_file_path.gsub ' ', '\ '} 2>&1").
100
225
  and_return("Total snapshots: 3\nsnap foo\nsnap bar\nsnap baz\n")
101
- @vm.snapshots.should == ['snap foo', 'snap bar', 'snap baz']
226
+
227
+ response = @vm.snapshots
228
+ response.should be_a_successful_response
229
+ response.data.should == ['snap foo', 'snap bar', 'snap baz']
102
230
  end
103
231
 
104
- it 'should print an error and exit if there was a problem getting the list of snapshots' do
232
+ it 'should return an unsuccessful response if unable to figure out the conf file' do
233
+ @conf_file_response_mock.stub_as_unsuccessful
234
+ @vm.snapshots.should be_an_unsuccessful_response
235
+ end
236
+
237
+ it 'should return an unsuccessful response if there was a problem getting the list of snapshots' do
105
238
  $?.should_receive(:exitstatus).and_return(1)
106
239
  @vm.should_receive(:`).
107
- with("#{@vmrun_cmd} listSnapshots #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
108
- and_return("it blew up\n")
109
- lambda { @vm.snapshots }.should raise_error SystemExit
110
- @string_io.string.should match /error getting the list of snapshots/
111
- @string_io.string.should match /error was.+it blew up/m
240
+ with("#{@vmrun_cmd} listSnapshots #{@conf_file_path.gsub ' ', '\ '} 2>&1").
241
+ and_return("it blew up")
242
+
243
+ @vm.snapshots.should be_an_unsuccessful_response
112
244
  end
113
245
  end
114
246
 
115
247
  describe 'create_snapshot' do
116
- it 'should create a snapshot' do
248
+ before do
249
+ @snapshots_response_mock = mock('snapshots')
250
+ @running_response_mock = mock('running?')
251
+
252
+ @running_response_mock.stub_as_successful true
253
+ @conf_file_response_mock.stub_as_successful @conf_file_path
254
+ @snapshots_response_mock.stub_as_successful []
255
+
256
+ @vm.stub(:exists?).and_return(true)
257
+ @vm.stub(:snapshots).and_return(@snapshots_response_mock)
258
+ @vm.stub(:running?).and_return(@running_response_mock)
259
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
260
+ end
261
+
262
+ it "should return an unsuccessful response if the vm doesn't exist" do
263
+ @vm.stub(:exists?).and_return(false)
264
+ @vm.create_snapshot('snap_1').should be_an_unsuccessful_response 'VM does not exist'
265
+ end
266
+
267
+ it 'should return an unsuccessful response if the vm is not running' do
268
+ @running_response_mock.stub_as_successful false
269
+
270
+ response = @vm.create_snapshot 'snap_1'
271
+ error_message = 'The VM must be running in order to take a snapshot.'
272
+ response.should be_an_unsuccessful_response error_message
273
+ end
274
+
275
+ it 'should return an unsuccessful response if unable to determine if running' do
276
+ @running_response_mock.stub_as_unsuccessful
277
+ @vm.create_snapshot('snap_1').should be_an_unsuccessful_response
278
+ end
279
+
280
+ it 'should return an unsuccessful response if unable to figure out the conf file' do
281
+ @conf_file_response_mock.stub_as_unsuccessful
282
+ @vm.create_snapshot('snap_1').should be_an_unsuccessful_response
283
+ end
284
+ it 'should return a successful response and create a snapshot' do
117
285
  $?.should_receive(:exitstatus).and_return(0)
118
286
  @vm.should_receive(:`).
119
- with("#{@vmrun_cmd} snapshot #{@vm.conf_file.gsub ' ', '\ '} \"bar\" 2>&1").
287
+ with("#{@vmrun_cmd} snapshot #{@conf_file_path.gsub ' ', '\ '} \"bar\" 2>&1").
120
288
  and_return("")
121
- @vm.create_snapshot('bar')
122
- @string_io.string.should match /Snapshot 'bar' created/
289
+
290
+ @vm.create_snapshot('bar').should be_a_successful_response
291
+ end
292
+
293
+ it 'should return an unsuccessful response if the snapshot name is a duplicate' do
294
+ @snapshots_response_mock.stub_as_successful ['snap_1']
295
+ response = @vm.create_snapshot 'snap_1'
296
+ response.should be_an_unsuccessful_response "There is already a snapshot named 'snap_1'."
297
+ end
298
+
299
+ it 'should return an unsuccessful response if there was a problem listing the existing snapshots' do
300
+ @snapshots_response_mock.stub_as_unsuccessful
301
+ @vm.create_snapshot('snap_1').should be_an_unsuccessful_response
123
302
  end
124
303
 
125
- it 'should print an error and exit if there was a problem creating the snapshot' do
304
+ it 'should return and unsuccessful response if there was a problem creating the snapshot' do
126
305
  $?.should_receive(:exitstatus).and_return(1)
127
306
  @vm.should_receive(:`).
128
- with("#{@vmrun_cmd} snapshot #{@vm.conf_file.gsub ' ', '\ '} \"bar\" 2>&1").
307
+ with("#{@vmrun_cmd} snapshot #{@conf_file_path.gsub ' ', '\ '} \"bar\" 2>&1").
129
308
  and_return("it blew up")
130
- lambda { @vm.create_snapshot('bar') }.should raise_error SystemExit
131
- @string_io.string.should match /error creating the snapshot/
132
- @string_io.string.should match /error was.+it blew up/m
309
+
310
+ @vm.create_snapshot('bar').should be_an_unsuccessful_response
133
311
  end
134
312
  end
135
313
 
136
314
  describe 'revert_to_snapshot' do
137
- it 'should revert to the provided snapshot' do
315
+ before do
316
+ @snapshots_response_mock = mock('snapshots')
317
+
318
+ @conf_file_response_mock.stub_as_successful @conf_file_path
319
+ @snapshots_response_mock.stub_as_successful ['snap_1']
320
+
321
+ @vm.stub(:exists?).and_return(true)
322
+ @vm.stub(:snapshots).and_return(@snapshots_response_mock)
323
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
324
+ Fission::Fusion.stub(:running?).and_return(false)
325
+ end
326
+
327
+ it "should return an unsuccessful response if the vm doesn't exist" do
328
+ @vm.stub(:exists?).and_return(false)
329
+ @vm.revert_to_snapshot('snap_1').should be_an_unsuccessful_response 'VM does not exist'
330
+ end
331
+
332
+ it 'should return an unsuccessful response if the Fusion GUI is running' do
333
+ Fission::Fusion.stub(:running?).and_return(true)
334
+
335
+ response = @vm.revert_to_snapshot 'snap_1'
336
+
337
+ error_string = 'It looks like the Fusion GUI is currently running. '
338
+ error_string << 'A VM cannot be reverted to a snapshot when the Fusion GUI is running. '
339
+ error_string << 'Exit the Fusion GUI and try again.'
340
+
341
+ response.should be_an_unsuccessful_response error_string
342
+ end
343
+
344
+ it 'should return an unsuccessful response if unable to figure out the conf file' do
345
+ @conf_file_response_mock.stub_as_unsuccessful
346
+ @vm.revert_to_snapshot('snap_1').should be_an_unsuccessful_response
347
+ end
348
+
349
+ it 'should return a successful response and revert to the provided snapshot' do
138
350
  $?.should_receive(:exitstatus).and_return(0)
139
351
  @vm.should_receive(:`).
140
- with("#{@vmrun_cmd} revertToSnapshot #{@vm.conf_file.gsub ' ', '\ '} \"bar\" 2>&1").
352
+ with("#{@vmrun_cmd} revertToSnapshot #{@conf_file_path.gsub ' ', '\ '} \"snap_1\" 2>&1").
141
353
  and_return("")
142
- @vm.revert_to_snapshot('bar')
143
- @string_io.string.should match /Reverted to snapshot 'bar'/
354
+
355
+ @vm.revert_to_snapshot('snap_1').should be_a_successful_response
144
356
  end
145
357
 
146
- it "should print an error and exit if the snapshot doesn't exist" do
358
+ it 'should return an unsuccessful response if the snapshot cannot be found' do
359
+ @snapshots_response_mock.stub_as_successful []
360
+ response = @vm.revert_to_snapshot 'snap_1'
361
+ response.should be_an_unsuccessful_response "Unable to find a snapshot named 'snap_1'."
362
+ end
363
+
364
+ it 'should return an unsuccessful response if unable to list the existing snapshots' do
365
+ @snapshots_response_mock.stub_as_unsuccessful
366
+ @vm.revert_to_snapshot('snap_1').should be_an_unsuccessful_response
367
+ end
368
+
369
+ it 'should return and unsuccessful response if unable to revert to the snapshot' do
147
370
  $?.should_receive(:exitstatus).and_return(1)
148
371
  @vm.should_receive(:`).
149
- with("#{@vmrun_cmd} revertToSnapshot #{@vm.conf_file.gsub ' ', '\ '} \"bar\" 2>&1").
372
+ with("#{@vmrun_cmd} revertToSnapshot #{@conf_file_path.gsub ' ', '\ '} \"snap_1\" 2>&1").
150
373
  and_return("it blew up")
151
- lambda { @vm.revert_to_snapshot('bar') }.should raise_error SystemExit
152
- @string_io.string.should match /error reverting to the snapshot/
153
- @string_io.string.should match /error was.+it blew up/m
374
+
375
+ @vm.revert_to_snapshot('snap_1').should be_an_unsuccessful_response
376
+ end
377
+
378
+ end
379
+
380
+ describe 'exists?' do
381
+ before do
382
+ @conf_file_response = mock('exists')
383
+ @vm.stub(:conf_file).and_return(@conf_file_response)
384
+ end
385
+
386
+ it 'should return true if the VM exists' do
387
+ @conf_file_response.stub_as_successful '/vms/foo/foo.vmx'
388
+ @vm.exists?.should == true
389
+ end
390
+
391
+ it 'should return false if the VM does not exist' do
392
+ @conf_file_response.stub_as_unsuccessful
393
+ @vm.exists?.should == false
394
+ end
395
+ end
396
+
397
+ describe 'mac_addresses' do
398
+ before do
399
+ @network_info_mock = mock('network_info')
400
+ @vm.should_receive(:network_info).and_return(@network_info_mock)
401
+ end
402
+
403
+ it 'should return a successful response with the list of mac addresses' do
404
+ network_data = { 'ethernet0' => { 'mac_address' => '00:0c:29:1d:6a:64',
405
+ 'ip_address' => '127.0.0.1' },
406
+ 'ethernet1' => { 'mac_address' => '00:0c:29:1d:6a:75',
407
+ 'ip_address' => '127.0.0.2' } }
408
+ @network_info_mock.stub_as_successful network_data
409
+
410
+ response = @vm.mac_addresses
411
+
412
+ response.should be_a_successful_response
413
+ response.data.should == ['00:0c:29:1d:6a:64', '00:0c:29:1d:6a:75']
414
+ end
415
+
416
+ it 'should return a successful response with an empty list if no mac addresses were found' do
417
+ @network_info_mock.stub_as_successful Hash.new
418
+
419
+ response = @vm.mac_addresses
420
+
421
+ response.should be_a_successful_response
422
+ response.data.should == []
423
+ end
424
+
425
+ it 'should return an unsuccessful response if there was an error getting the mac addresses' do
426
+ @network_info_mock.stub_as_unsuccessful
427
+
428
+ response = @vm.mac_addresses
429
+
430
+ response.should be_an_unsuccessful_response
431
+ response.data.should be_nil
432
+ end
433
+
434
+ end
435
+
436
+ describe 'network_info' do
437
+ before do
438
+ @conf_file_response_mock.stub_as_successful @conf_file_path
439
+
440
+ @vm.should_receive(:conf_file).and_return(@conf_file_response_mock)
441
+ @conf_file_io = StringIO.new
442
+ @lease_1_response_mock = mock('lease_1_response')
443
+ @lease_2_response_mock = mock('lease_1_response')
444
+ end
445
+
446
+ it 'should return a successful response with the list of interfaces, macs, and ips' do
447
+ @conf_file_response_mock.stub_as_successful @conf_file_path
448
+
449
+ @lease_1 = Fission::Lease.new :ip_address => '127.0.0.1',
450
+ :mac_address => '00:0c:29:1d:6a:64'
451
+ @lease_1_response_mock.stub_as_successful @lease_1
452
+
453
+ @lease_2 = Fission::Lease.new :ip_address => '127.0.0.2',
454
+ :mac_address => '00:0c:29:1d:6a:75'
455
+ @lease_2_response_mock.stub_as_successful @lease_2
456
+
457
+ vmx_content = 'ide1:0.deviceType = "cdrom-image"
458
+ ethernet0.present = "TRUE"
459
+ ethernet1.address = "00:0c:29:1d:6a:75"
460
+ ethernet0.connectionType = "nat"
461
+ ethernet0.generatedAddress = "00:0c:29:1d:6a:64"
462
+ ethernet0.virtualDev = "e1000"
463
+ ethernet0.wakeOnPcktRcv = "FALSE"
464
+ ethernet0.addressType = "generated"
465
+ ethernet0.linkStatePropagation.enable = "TRUE"
466
+ ethernet0.generatedAddressenable = "TRUE"
467
+ ethernet1.generatedAddressenable = "TRUE"'
468
+
469
+ @conf_file_io.string = vmx_content
470
+
471
+ File.should_receive(:open).with(@conf_file_path, 'r').
472
+ and_yield(@conf_file_io)
473
+
474
+ Fission::Lease.should_receive(:find_by_mac_address).
475
+ with('00:0c:29:1d:6a:64').
476
+ and_return(@lease_1_response_mock)
477
+ Fission::Lease.should_receive(:find_by_mac_address).
478
+ with('00:0c:29:1d:6a:75').
479
+ and_return(@lease_2_response_mock)
480
+
481
+ response = @vm.network_info
482
+ response.should be_a_successful_response
483
+ response.data.should == { 'ethernet0' => { 'mac_address' => '00:0c:29:1d:6a:64',
484
+ 'ip_address' => '127.0.0.1' },
485
+ 'ethernet1' => { 'mac_address' => '00:0c:29:1d:6a:75',
486
+ 'ip_address' => '127.0.0.2' } }
487
+ end
488
+
489
+ it 'should return a successful response with an empty list if there are no macs' do
490
+
491
+ vmx_content = 'ide1:0.deviceType = "cdrom-image"
492
+ pciBridge7.virtualDev = "pcieRootPort"
493
+ pciBridge7.functions = "8"
494
+ vmci0.present = "TRUE"
495
+ roamingVM.exitBehavior = "go"
496
+ tools.syncTime = "TRUE"'
497
+
498
+ @conf_file_io.string = vmx_content
499
+
500
+ File.should_receive(:open).with(@conf_file_path, 'r').
501
+ and_yield(@conf_file_io)
502
+
503
+ response = @vm.network_info
504
+ response.should be_a_successful_response
505
+ response.data.should == {}
506
+ end
507
+
508
+ it 'should return a successful response without ip addresses if none were found' do
509
+ @lease_1_response_mock.stub_as_successful nil
510
+ @lease_2_response_mock.stub_as_successful nil
511
+
512
+ vmx_content = 'ide1:0.deviceType = "cdrom-image"
513
+ ethernet0.present = "TRUE"
514
+ ethernet1.address = "00:0c:29:1d:6a:75"
515
+ ethernet0.connectionType = "nat"
516
+ ethernet0.generatedAddress = "00:0c:29:1d:6a:64"
517
+ ethernet0.virtualDev = "e1000"
518
+ ethernet0.wakeOnPcktRcv = "FALSE"
519
+ ethernet0.addressType = "generated"
520
+ ethernet0.linkStatePropagation.enable = "TRUE"
521
+ ethernet0.generatedAddressenable = "TRUE"
522
+ ethernet1.generatedAddressenable = "TRUE"'
523
+
524
+ @conf_file_io.string = vmx_content
525
+
526
+ File.should_receive(:open).with(@conf_file_path, 'r').
527
+ and_yield(@conf_file_io)
528
+
529
+ Fission::Lease.should_receive(:find_by_mac_address).
530
+ with('00:0c:29:1d:6a:64').
531
+ and_return(@lease_1_response_mock)
532
+ Fission::Lease.should_receive(:find_by_mac_address).
533
+ with('00:0c:29:1d:6a:75').
534
+ and_return(@lease_2_response_mock)
535
+
536
+ response = @vm.network_info
537
+ response.should be_a_successful_response
538
+ response.data.should == { 'ethernet0' => { 'mac_address' => '00:0c:29:1d:6a:64',
539
+ 'ip_address' => nil },
540
+ 'ethernet1' => { 'mac_address' => '00:0c:29:1d:6a:75',
541
+ 'ip_address' => nil } }
542
+ end
543
+
544
+ it 'should return an unsuccessful response with an error if no conf file was found' do
545
+ @conf_file_response_mock.stub_as_unsuccessful
546
+
547
+ File.should_not_receive(:open)
548
+
549
+ @vm.network_info.should be_an_unsuccessful_response
550
+ end
551
+
552
+ it 'should return an unsuccessful response if there was an error getting the ip information' do
553
+ @lease_1_response_mock.stub_as_unsuccessful
554
+ @lease_2_response_mock.stub_as_successful nil
555
+
556
+ vmx_content = 'ide1:0.deviceType = "cdrom-image"
557
+ ethernet0.present = "TRUE"
558
+ ethernet1.address = "00:0c:29:1d:6a:75"
559
+ ethernet0.connectionType = "nat"
560
+ ethernet0.generatedAddress = "00:0c:29:1d:6a:64"
561
+ ethernet0.virtualDev = "e1000"
562
+ ethernet0.wakeOnPcktRcv = "FALSE"
563
+ ethernet0.addressType = "generated"
564
+ ethernet0.linkStatePropagation.enable = "TRUE"
565
+ ethernet0.generatedAddressenable = "TRUE"
566
+ ethernet1.generatedAddressenable = "TRUE"'
567
+
568
+ @conf_file_io.string = vmx_content
569
+
570
+ File.should_receive(:open).with(@conf_file_path, 'r').
571
+ and_yield(@conf_file_io)
572
+
573
+ Fission::Lease.should_receive(:find_by_mac_address).
574
+ with('00:0c:29:1d:6a:64').
575
+ and_return(@lease_1_response_mock)
576
+ Fission::Lease.should_receive(:find_by_mac_address).
577
+ with('00:0c:29:1d:6a:75').
578
+ and_return(@lease_2_response_mock)
579
+
580
+ @vm.network_info.should be_an_unsuccessful_response
581
+ end
582
+ end
583
+
584
+ describe 'path' do
585
+ it 'should return the path of the VM' do
586
+ vm_path = File.join(Fission.config['vm_dir'], 'foo.vmwarevm').gsub '\\', ''
587
+ Fission::VM.new('foo').path.should == vm_path
588
+ end
589
+ end
590
+
591
+ describe 'state' do
592
+ before do
593
+ @vm_1 = Fission::VM.new 'foo'
594
+ @vm_2 = Fission::VM.new 'bar'
595
+
596
+ @all_running_response_mock = mock('all_running')
597
+ @suspended_response_mock = mock('suspended')
598
+
599
+ Fission::VM.stub(:all_running).and_return(@all_running_response_mock)
600
+ @all_running_response_mock.stub_as_successful [@vm_2]
601
+ end
602
+
603
+ it "should return a successful response and 'not running' when the VM is off" do
604
+ response = @vm.state
605
+ response.should be_a_successful_response
606
+ response.data.should == 'not running'
607
+ end
608
+
609
+ it "should return a successful resopnse and 'running' when the VM is running" do
610
+ @all_running_response_mock.stub_as_successful [@vm_1, @vm_2]
611
+
612
+ response = @vm.state
613
+ response.should be_a_successful_response
614
+ response.data.should == 'running'
615
+ end
616
+
617
+ it "should return a successful response and 'suspended' when the VM is suspended" do
618
+ @suspended_response_mock.stub_as_successful true
619
+
620
+ @vm.stub(:suspended?).and_return(@suspended_response_mock)
621
+
622
+ response = @vm.state
623
+ response.should be_a_successful_response
624
+ response.data.should == 'suspended'
625
+ end
626
+
627
+ it 'should return an unsuccessful response if there was an error getting the running VMs' do
628
+ @all_running_response_mock.stub_as_unsuccessful
629
+ @vm.state.should be_an_unsuccessful_response
630
+ end
631
+
632
+ it 'should return an unsuccessful repsonse if there was an error determining if the VM is suspended' do
633
+ @suspended_response_mock.stub_as_unsuccessful
634
+ @vm.stub(:suspended?).and_return(@suspended_response_mock)
635
+ @vm.state.should be_an_unsuccessful_response
636
+ end
637
+ end
638
+
639
+ describe 'running?' do
640
+ before do
641
+ @all_running_response_mock = mock('all_running')
642
+
643
+ Fission::VM.stub(:all_running).and_return(@all_running_response_mock)
644
+ end
645
+
646
+ it 'should return a successful response and false when the vm is not running' do
647
+ @all_running_response_mock.stub_as_successful []
648
+ response = @vm.running?
649
+ response.should be_a_successful_response
650
+ response.data.should == false
651
+ end
652
+
653
+ it 'should return a successful response and true if the vm is running' do
654
+ @all_running_response_mock.stub_as_successful [Fission::VM.new('foo')]
655
+
656
+ response = @vm.running?
657
+ response.should be_a_successful_response
658
+ response.data.should == true
659
+ end
660
+
661
+ it 'should return an unsuccessful repsponse if there is an error getting the list of running vms' do
662
+ @all_running_response_mock.stub_as_unsuccessful
663
+ @vm.running?.should be_an_unsuccessful_response
664
+ end
665
+
666
+ end
667
+
668
+ describe 'suspend_file_exists?' do
669
+ before do
670
+ FakeFS.activate!
671
+ FileUtils.mkdir_p @vm.path
672
+ end
673
+
674
+ after do
675
+ FakeFS.deactivate!
676
+ FakeFS::FileSystem.clear
154
677
  end
678
+
679
+ it 'should return true if the suspend file exists' do
680
+ FileUtils.touch(File.join(@vm.path, "#{@vm.name}.vmem"))
681
+ @vm.suspend_file_exists?.should == true
682
+ end
683
+
684
+ it 'should return false if the suspend file does not exist' do
685
+ @vm.suspend_file_exists?.should == false
686
+ end
687
+
688
+ end
689
+
690
+ describe 'suspended?' do
691
+ before do
692
+ @running_response_mock = mock('running?')
693
+ @vm.stub(:running?).and_return(@running_response_mock)
694
+ end
695
+
696
+ describe 'when the vm is not running' do
697
+ before do
698
+ @running_response_mock.stub_as_successful false
699
+ end
700
+
701
+ it 'should return a successful response and true if a .vmem file exists in the vm dir' do
702
+ @vm.stub(:suspend_file_exists?).and_return(true)
703
+
704
+ response = @vm.suspended?
705
+ response.should be_a_successful_response
706
+ response.data.should == true
707
+ end
708
+
709
+ it 'should return a successful response and false if a .vmem file is not found in the vm dir' do
710
+ @vm.stub(:suspend_file_exists?).and_return(false)
711
+
712
+ response = @vm.suspended?
713
+ response.should be_a_successful_response
714
+ response.data.should == false
715
+ end
716
+ end
717
+
718
+ it 'should return a successful response and false if the vm is running' do
719
+ @running_response_mock.stub_as_successful true
720
+
721
+ response = @vm.suspended?
722
+ response.should be_a_successful_response
723
+ response.data.should == false
724
+ end
725
+
726
+ it 'should return an unsuccessful repsponse if there is an error getting the list of running vms' do
727
+ @running_response_mock.stub_as_unsuccessful
728
+ @vm.suspended?.should be_an_unsuccessful_response
729
+ end
730
+
155
731
  end
156
732
 
157
733
  describe 'conf_file' do
158
734
  before do
159
735
  FakeFS.activate!
160
- @vm_root_dir = Fission::VM.path('foo')
736
+ @vm_root_dir = Fission::VM.new('foo').path
161
737
  FileUtils.mkdir_p(@vm_root_dir)
162
738
  end
163
739
 
@@ -166,71 +742,85 @@ describe Fission::VM do
166
742
  FakeFS::FileSystem.clear
167
743
  end
168
744
 
169
- it 'should return the path to the conf file' do
745
+ it 'should return a successful response with the path to the conf file' do
170
746
  file_path = File.join(@vm_root_dir, 'foo.vmx')
171
747
  FileUtils.touch(file_path)
172
- Fission::VM.new('foo').conf_file.should == file_path
173
- end
174
748
 
175
- it 'should output an error and exit if no vmx file was found' do
176
- lambda {
177
- FileUtils.mkdir_p(@vm_root_dir)
178
- Fission::VM.new('foo').conf_file
179
- }.should raise_error SystemExit
749
+ response = Fission::VM.new('foo').conf_file
750
+ response.should be_a_successful_response
751
+ response.data.should == file_path
752
+ end
180
753
 
181
- @string_io.string.should match /Unable to find a config file for VM 'foo' \(in '#{File.join(@vm_root_dir, '\*\.vmx')}'\)/m
754
+ it 'should return an unsuccessful response with an error if no vmx file was found' do
755
+ response = Fission::VM.new('foo').conf_file
756
+ response.successful?.should == false
757
+ response.message.should match /Unable to find a config file for VM 'foo' \(in '#{File.join(@vm_root_dir, '\*\.vmx')}'\)/m
182
758
  end
183
759
 
184
760
  describe 'when the VM name and conf file name do not match' do
185
761
  it 'should return the path to the conf file' do
186
762
  file_path = File.join(@vm_root_dir, 'bar.vmx')
187
763
  FileUtils.touch(file_path)
188
- Fission::VM.new('foo').conf_file.should == file_path
764
+
765
+ response = Fission::VM.new('foo').conf_file
766
+ response.should be_a_successful_response
767
+ response.data.should == file_path
189
768
  end
190
769
  end
191
770
 
192
771
  describe 'if multiple vmx files are found' do
193
- before do
194
- FileUtils.mkdir_p(@vm_root_dir)
195
- end
196
-
197
- it 'should use the conf file which matches the VM name if it exists' do
772
+ it 'should use return a successful response with the conf file which matches the VM name if it exists' do
198
773
  ['foo.vmx', 'bar.vmx'].each do |file|
199
774
  FileUtils.touch(File.join(@vm_root_dir, file))
200
775
  end
201
- Fission::VM.new('foo').conf_file.should == File.join(@vm_root_dir, 'foo.vmx')
776
+
777
+ response = Fission::VM.new('foo').conf_file
778
+ response.should be_a_successful_response
779
+ response.data.should == File.join(@vm_root_dir, 'foo.vmx')
202
780
  end
203
781
 
204
- it 'should output an error and exit' do
205
- lambda {
206
- ['bar.vmx', 'baz.vmx'].each do |file|
207
- FileUtils.touch(File.join(@vm_root_dir, file))
208
- end
209
- Fission::VM.new('foo').conf_file
210
- }.should raise_error SystemExit
782
+ it 'should return an unsuccessful object if none of the conf files matches the VM name' do
783
+ ['bar.vmx', 'baz.vmx'].each do |file|
784
+ FileUtils.touch(File.join(@vm_root_dir, file))
785
+ end
786
+ Fission::VM.new('foo').conf_file
211
787
 
212
- @string_io.string.should match /Multiple config files found for VM 'foo' \('bar\.vmx', 'baz\.vmx' in '#{@vm_root_dir}'/m
788
+ response = Fission::VM.new('foo').conf_file
789
+ response.successful?.should == false
790
+ error_regex = /Multiple config files found for VM 'foo' \('bar\.vmx', 'baz\.vmx' in '#{@vm_root_dir}'/m
791
+ response.message.should match error_regex
213
792
  end
214
793
  end
215
794
 
216
795
  end
217
796
 
218
797
  describe "self.all" do
219
- it "should return the list of VMs" do
220
- vm_root = Fission.config.attributes['vm_dir']
798
+ before do
799
+ @vm_1_mock = mock('vm_1')
800
+ @vm_2_mock = mock('vm_2')
801
+ end
802
+
803
+ it "should return a successful object with the list of VM objects" do
804
+ vm_root = Fission.config['vm_dir']
221
805
  Dir.should_receive(:[]).
222
806
  and_return(["#{File.join vm_root, 'foo.vmwarevm' }", "#{File.join vm_root, 'bar.vmwarevm' }"])
223
807
 
224
- vm_root = Fission.config.attributes['vm_dir']
808
+ vm_root = Fission.config['vm_dir']
225
809
  File.should_receive(:directory?).with("#{File.join vm_root, 'foo.vmwarevm'}").
226
810
  and_return(true)
227
811
  File.should_receive(:directory?).with("#{File.join vm_root, 'bar.vmwarevm'}").
228
812
  and_return(true)
229
- Fission::VM.all.should == ['foo', 'bar']
813
+
814
+ Fission::VM.should_receive(:new).with('foo').and_return(@vm_1_mock)
815
+ Fission::VM.should_receive(:new).with('bar').and_return(@vm_2_mock)
816
+
817
+ response = Fission::VM.all
818
+ response.should be_a_successful_response
819
+ response.data.should == [@vm_1_mock, @vm_2_mock]
230
820
  end
231
821
 
232
- it "should not return an item in the list if it isn't a directory" do
233
- vm_root = Fission.config.attributes['vm_dir']
822
+ it "should return a successful object and not return an item in the list if it isn't a directory" do
823
+ vm_root = Fission.config['vm_dir']
234
824
  Dir.should_receive(:[]).
235
825
  and_return((['foo', 'bar', 'baz'].map { |i| File.join vm_root, "#{i}.vmwarevm"}))
236
826
  File.should_receive(:directory?).
@@ -239,11 +829,17 @@ describe Fission::VM do
239
829
  with("#{File.join vm_root, 'bar.vmwarevm'}").and_return(true)
240
830
  File.should_receive(:directory?).
241
831
  with("#{File.join vm_root, 'baz.vmwarevm'}").and_return(false)
242
- Fission::VM.all.should == ['foo', 'bar']
832
+
833
+ Fission::VM.should_receive(:new).with('foo').and_return(@vm_1_mock)
834
+ Fission::VM.should_receive(:new).with('bar').and_return(@vm_2_mock)
835
+
836
+ response = Fission::VM.all
837
+ response.should be_a_successful_response
838
+ response.data.should == [@vm_1_mock, @vm_2_mock]
243
839
  end
244
840
 
245
841
  it "should only query for items with an extension of .vmwarevm" do
246
- dir_arg = File.join Fission.config.attributes['vm_dir'], '*.vmwarevm'
842
+ dir_arg = File.join Fission.config['vm_dir'], '*.vmwarevm'
247
843
  Dir.should_receive(:[]).with(dir_arg).
248
844
  and_return(['foo.vmwarevm', 'bar.vmwarevm'])
249
845
  Fission::VM.all
@@ -251,7 +847,14 @@ describe Fission::VM do
251
847
  end
252
848
 
253
849
  describe 'self.all_running' do
254
- it 'should list the running vms' do
850
+ before do
851
+ @vm_1 = Fission::VM.new 'foo'
852
+ @vm_2 = Fission::VM.new 'bar'
853
+ @vm_3 = Fission::VM.new 'baz'
854
+ @vm_names_and_objs = { 'foo' => @vm_1, 'bar' => @vm_2, 'baz' => @vm_3 }
855
+ end
856
+
857
+ it 'should return a successful response with the list of running vms' do
255
858
  list_output = "Total running VMs: 2\n/vm/foo.vmwarevm/foo.vmx\n"
256
859
  list_output << "/vm/bar.vmwarevm/bar.vmx\n/vm/baz.vmwarevm/baz.vmx\n"
257
860
 
@@ -262,18 +865,25 @@ describe Fission::VM do
262
865
  [ 'foo', 'bar', 'baz'].each do |vm|
263
866
  File.should_receive(:exists?).with("/vm/#{vm}.vmwarevm/#{vm}.vmx").
264
867
  and_return(true)
868
+
869
+ Fission::VM.should_receive(:new).with(vm).
870
+ and_return(@vm_names_and_objs[vm])
265
871
  end
266
872
 
267
- Fission::VM.all_running.should == ['foo', 'bar', 'baz']
873
+ response = Fission::VM.all_running
874
+ response.should be_a_successful_response
875
+ response.data.should == [@vm_1, @vm_2, @vm_3]
268
876
  end
269
877
 
270
- it 'should output the VM dir name if it differs from the .vmx file name' do
878
+ it 'should return a successful response with the VM dir name if it differs from the .vmx file name' do
271
879
  vm_dir_file = { 'foo' => 'foo', 'bar' => 'diff', 'baz' => 'baz'}
272
880
  list_output = "Total running VMs: 3\n"
273
881
  vm_dir_file.each_pair do |dir, file|
274
882
  list_output << "/vm/#{dir}.vmwarevm/#{file}.vmx\n"
275
883
  File.should_receive(:exists?).with("/vm/#{dir}.vmwarevm/#{file}.vmx").
276
884
  and_return(true)
885
+ Fission::VM.should_receive(:new).with(dir).
886
+ and_return(@vm_names_and_objs[dir])
277
887
  end
278
888
 
279
889
  $?.should_receive(:exitstatus).and_return(0)
@@ -281,70 +891,80 @@ describe Fission::VM do
281
891
  with("#{@vmrun_cmd} list").
282
892
  and_return(list_output)
283
893
 
284
- Fission::VM.all_running.should == ['foo', 'bar', 'baz']
894
+ response = Fission::VM.all_running
895
+ response.should be_a_successful_response
896
+ response.data.should == [@vm_1, @vm_2, @vm_3]
285
897
  end
286
898
 
287
- it 'should output an error and exit if unable to get the list of running vms' do
899
+ it 'should return an unsuccessful response if unable to get the list of running vms' do
288
900
  $?.should_receive(:exitstatus).and_return(1)
289
901
  Fission::VM.should_receive(:`).
290
902
  with("#{@vmrun_cmd} list").
291
903
  and_return("it blew up")
292
904
  Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
293
905
 
294
- lambda {
295
- Fission::VM.all_running
296
- }.should raise_error SystemExit
297
-
298
- @string_io.string.should match /Unable to determine the list of running VMs/
299
- end
300
- end
301
-
302
- describe "self.path" do
303
- it "should return the path of the vm" do
304
- vm_path = File.join(Fission.config.attributes['vm_dir'], 'foo.vmwarevm').gsub '\\', ''
305
- Fission::VM.path('foo').should == vm_path
306
- end
307
- end
308
-
309
- describe "self.exists?" do
310
- it "should return true if the vm exists" do
311
- FakeFS do
312
- FileUtils.mkdir_p(Fission::VM.path('foo'))
313
- Fission::VM.exists?('foo').should == true
314
- end
315
- end
316
-
317
- it 'should return false if the vm does not exist' do
318
- FakeFS do
319
- FileUtils.rm_r(Fission::VM.path('foo'))
320
- Fission::VM.exists?('foo').should == false
321
- end
906
+ Fission::VM.all_running.should be_an_unsuccessful_response
322
907
  end
323
908
  end
324
909
 
325
910
  describe "self.clone" do
326
911
  before do
327
- @source_vm = 'foo'
328
- @target_vm = 'bar'
912
+ @source_vm = Fission::VM.new 'foo'
913
+ @target_vm = Fission::VM.new 'bar'
914
+ @source_path = @source_vm.path
915
+ @target_path = @target_vm.path
916
+
917
+ @clone_response_mock = mock('clone_response')
329
918
  @vm_files = ['.vmx', '.vmxf', '.vmdk', '-s001.vmdk', '-s002.vmdk', '.vmsd']
330
919
 
331
920
  FakeFS.activate!
332
921
 
333
- FileUtils.mkdir_p Fission::VM.path('foo')
922
+ FileUtils.mkdir_p @source_path
334
923
 
335
924
  @vm_files.each do |file|
336
- FileUtils.touch File.join(Fission::VM.path('foo'), "#{@source_vm}#{file}")
925
+ FileUtils.touch "#{@source_path}/#{@source_vm.name}#{file}"
337
926
  end
338
927
 
339
928
  ['.vmx', '.vmxf', '.vmdk'].each do |ext|
340
- File.open(File.join(Fission::VM.path('foo'), "foo#{ext}"), 'w') { |f| f.write 'foo.vmdk'}
929
+ File.open("#{@source_path}/foo#{ext}", 'w') { |f| f.write 'foo.vmdk'}
930
+ end
931
+
932
+ @source_vm.stub(:exists?).and_return(true)
933
+ @target_vm.stub(:exists?).and_return(false)
934
+
935
+ Fission::VM.stub(:new).with(@source_vm.name).
936
+ and_return(@source_vm)
937
+ Fission::VM.stub(:new).with(@target_vm.name).
938
+ and_return(@target_vm)
939
+
940
+ vmx_content = 'ide1:0.deviceType = "cdrom-image"
941
+ nvram = "foo.nvram"
942
+ ethernet0.present = "TRUE"
943
+ ethernet1.address = "00:0c:29:1d:6a:75"
944
+ ethernet0.connectionType = "nat"
945
+ ethernet0.generatedAddress = "00:0c:29:1d:6a:64"
946
+ ethernet0.virtualDev = "e1000"
947
+ tools.remindInstall = "TRUE"
948
+ ethernet0.wakeOnPcktRcv = "FALSE"
949
+ ethernet0.addressType = "generated"
950
+ uuid.action = "keep"
951
+ ethernet0.linkStatePropagation.enable = "TRUE"
952
+ ethernet0.generatedAddressenable = "TRUE"
953
+ ethernet1.generatedAddressenable = "TRUE"'
954
+
955
+ File.open("#{@source_path}/#{@source_vm.name}.vmx", 'w') do |f|
956
+ f.write vmx_content
341
957
  end
342
958
 
343
959
  ['.vmx', '.vmxf'].each do |ext|
344
- File.should_receive(:binary?).
345
- with(File.join(Fission::VM.path('bar'), "bar#{ext}")).
960
+ File.stub(:binary?).
961
+ with("#{@target_path}/#{@target_vm.name}#{ext}").
346
962
  and_return(false)
347
963
  end
964
+
965
+ File.stub(:binary?).
966
+ with("#{@target_path}/#{@target_vm.name}.vmdk").
967
+ and_return(true)
348
968
  end
349
969
 
350
970
  after do
@@ -352,100 +972,129 @@ describe Fission::VM do
352
972
  FakeFS::FileSystem.clear
353
973
  end
354
974
 
975
+ it "should return an unsuccessful response if the source vm doesn't exist" do
976
+ @source_vm.stub(:exists?).and_return(false)
977
+ response = Fission::VM.clone @source_vm.name, @target_vm.name
978
+ response.should be_an_unsuccessful_response 'VM does not exist'
979
+ end
980
+
981
+ it "should return an unsuccessful response if the target vm exists" do
982
+ @target_vm.stub(:exists?).and_return(true)
983
+ response = Fission::VM.clone @source_vm.name, @target_vm.name
984
+ response.should be_an_unsuccessful_response 'VM already exists'
985
+ end
986
+
355
987
  it 'should copy the vm files to the target' do
356
- File.should_receive(:binary?).
357
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).
358
- and_return(true)
359
- Fission::VM.clone @source_vm, @target_vm
988
+ Fission::VM.clone @source_vm.name, @target_vm.name
360
989
 
361
- File.directory?(Fission::VM.path('bar')).should == true
990
+ File.directory?(@target_path).should == true
362
991
 
363
992
  @vm_files.each do |file|
364
- File.file?(File.join(Fission::VM.path('bar'), "#{@target_vm}#{file}")).should == true
993
+ File.file?("#{@target_path}/bar#{file}").should == true
365
994
  end
366
995
  end
367
996
 
368
997
  it "should copy the vm files to the target if a file name doesn't match the directory" do
369
- FileUtils.touch File.join(Fission::VM.path('foo'), 'other_name.nvram')
370
- File.should_receive(:binary?).
371
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).
372
- and_return(true)
373
- Fission::VM.clone @source_vm, @target_vm
998
+ FileUtils.touch "#{@source_path}/other_name.nvram"
999
+
1000
+ Fission::VM.clone @source_vm.name, @target_vm.name
374
1001
 
375
- File.directory?(Fission::VM.path('bar')).should == true
1002
+ File.directory?(@target_path).should == true
376
1003
 
377
1004
  @vm_files.each do |file|
378
- File.file?(File.join(Fission::VM.path('bar'), "#{@target_vm}#{file}")).should == true
1005
+ File.file?("#{@target_path}/#{@target_vm.name}#{file}").should == true
379
1006
  end
380
1007
 
381
- File.file?(File.join(Fission::VM.path('bar'), "bar.nvram")).should == true
1008
+ File.file?("#{@target_path}/bar.nvram").should == true
382
1009
  end
383
1010
 
384
-
385
1011
  it "should copy the vm files to the target if a sparse disk file name doesn't match the directory" do
386
- FileUtils.touch File.join(Fission::VM.path('foo'), 'other_name-s003.vmdk')
387
- File.should_receive(:binary?).
388
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).
389
- and_return(true)
390
- Fission::VM.clone @source_vm, @target_vm
1012
+ FileUtils.touch "#{@source_path}/other_name-s003.vmdk"
1013
+
1014
+ Fission::VM.clone @source_vm.name, @target_vm.name
391
1015
 
392
- File.directory?(Fission::VM.path('bar')).should == true
1016
+ File.directory?(@target_path).should == true
393
1017
 
394
1018
  @vm_files.each do |file|
395
- File.file?(File.join(Fission::VM.path('bar'), "#{@target_vm}#{file}")).should == true
1019
+ File.file?("#{@target_path}/#{@target_vm.name}#{file}").should == true
396
1020
  end
397
1021
 
398
- File.file?(File.join(Fission::VM.path('bar'), "bar-s003.vmdk")).should == true
1022
+ File.file?("#{@target_path}/bar-s003.vmdk").should == true
399
1023
  end
400
1024
 
401
1025
  it 'should update the target vm config files' do
402
- File.should_receive(:binary?).
403
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).
404
- and_return(true)
405
- Fission::VM.clone @source_vm, @target_vm
1026
+ Fission::VM.clone @source_vm.name, @target_vm.name
406
1027
 
407
1028
  ['.vmx', '.vmxf'].each do |ext|
408
- File.read(File.join(Fission::VM.path('bar'), "bar#{ext}")).should_not match /foo/
409
- File.read(File.join(Fission::VM.path('bar'), "bar#{ext}")).should match /bar/
1029
+ File.read("#{@target_path}/bar#{ext}").should_not match /foo/
1030
+ File.read("#{@target_path}/bar#{ext}").should match /bar/
410
1031
  end
411
1032
  end
412
1033
 
413
- it "should not try to update the vmdk file if it's not a sparse disk" do
414
- File.should_receive(:binary?).
415
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(true)
416
- Fission::VM.clone @source_vm, @target_vm
1034
+ it 'should disable VMware tools warning in the conf file' do
1035
+ Fission::VM.clone @source_vm.name, @target_vm.name
1036
+
1037
+ pattern = /^tools\.remindInstall = "FALSE"/
417
1038
 
418
- File.read(File.join(Fission::VM.path('bar'), 'bar.vmdk')).should match /foo/
1039
+ File.read("#{@target_path}/bar.vmx").should match pattern
419
1040
  end
420
1041
 
421
- it "should update the vmdk when a sparse disk is found" do
422
- File.should_receive(:binary?).
423
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(false)
424
- Fission::VM.clone @source_vm, @target_vm
1042
+ it 'should remove auto generated MAC addresses from the conf file' do
1043
+ Fission::VM.clone @source_vm.name, @target_vm.name
1044
+
1045
+ pattern = /^ethernet\.+generatedAddress.+/
1046
+
1047
+ File.read("#{@target_path}/bar.vmx").should_not match pattern
1048
+ end
1049
+
1050
+ it 'should setup the conf file to generate a new uuid' do
1051
+ Fission::VM.clone @source_vm.name, @target_vm.name
1052
+
1053
+ pattern = /^uuid\.action = "create"/
1054
+
1055
+ File.read("#{@target_path}/bar.vmx").should match pattern
1056
+ end
1057
+
1058
+ it "should not try to update the vmdk file if it's not a sparse disk" do
1059
+ Fission::VM.clone @source_vm.name, @target_vm.name
1060
+
1061
+ File.read("#{@target_path}/bar.vmdk").should match /foo/
1062
+ end
425
1063
 
426
- File.read(File.join(Fission::VM.path('bar'), 'bar.vmdk')).should match /bar/
1064
+ it 'should return a successful response if clone was successful' do
1065
+ Fission::VM.clone(@source_vm.name, @target_vm.name).should be_a_successful_response
427
1066
  end
428
1067
 
429
- it 'should output that the clone was successful' do
430
- File.should_receive(:binary?).
431
- with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(true)
432
- Fission::VM.clone @source_vm, @target_vm
1068
+ describe 'when a sparse disk is found' do
1069
+ it "should update the vmdk" do
1070
+ File.rspec_reset
1071
+ File.stub(:binary?).and_return(false)
433
1072
 
434
- @string_io.string.should match /Cloning #{@source_vm} to #{@target_vm}/
435
- @string_io.string.should match /Configuring #{@target_vm}/
1073
+ Fission::VM.clone @source_vm.name, @target_vm.name
1074
+
1075
+ File.read("#{@target_path}/bar.vmdk").should match /bar/
1076
+ end
436
1077
  end
1078
+
437
1079
  end
438
1080
 
439
- describe "self.delete" do
1081
+ describe 'delete' do
440
1082
  before do
1083
+ @running_response_mock = mock('running?')
1084
+ @running_response_mock.stub_as_successful false
1085
+
1086
+ @vm.stub(:exists?).and_return(true)
1087
+ @vm.stub(:running?).and_return(@running_response_mock)
1088
+ @vm.stub(:conf_file).and_return(@conf_file_response_mock)
1089
+
441
1090
  @target_vm = 'foo'
442
1091
  @vm_files = %w{ .vmx .vmxf .vmdk -s001.vmdk -s002.vmdk .vmsd }
443
1092
  FakeFS.activate!
444
1093
 
445
- FileUtils.mkdir_p Fission::VM.path(@target_vm)
1094
+ FileUtils.mkdir_p Fission::VM.new(@target_vm).path
446
1095
 
447
1096
  @vm_files.each do |file|
448
- FileUtils.touch File.join(Fission::VM.path(@target_vm), "#{@target_vm}#{file}")
1097
+ FileUtils.touch File.join(Fission::VM.new(@target_vm).path, "#{@target_vm}#{file}")
449
1098
  end
450
1099
  end
451
1100
 
@@ -453,18 +1102,45 @@ describe Fission::VM do
453
1102
  FakeFS.deactivate!
454
1103
  end
455
1104
 
1105
+ it "should return an unsuccessful response if the vm doesn't exist" do
1106
+ @vm.stub(:exists?).and_return(false)
1107
+
1108
+ response = @vm.delete
1109
+ response.should be_an_unsuccessful_response 'VM does not exist'
1110
+ end
1111
+
1112
+ it 'should return an unsuccessful response if the vm is running' do
1113
+ @running_response_mock.stub_as_successful true
1114
+
1115
+ response = @vm.delete
1116
+ response.should be_an_unsuccessful_response 'The VM must not be running in order to delete it.'
1117
+ end
1118
+
1119
+ it 'should return an unsuccessful response if unable to determine if running' do
1120
+ @running_response_mock.stub_as_unsuccessful
1121
+
1122
+ response = @vm.delete
1123
+ response.should be_an_unsuccessful_response
1124
+ end
1125
+
456
1126
  it "should delete the target vm files" do
457
1127
  Fission::Metadata.stub!(:delete_vm_info)
458
- Fission::VM.delete @target_vm
1128
+
1129
+ @vm.delete
1130
+
459
1131
  @vm_files.each do |file|
460
- File.exists?(File.join(Fission::VM.path(@target_vm), "#{@target_vm}#{file}")).should == false
1132
+ File.exists?(File.join(Fission::VM.new(@target_vm).path, "#{@target_vm}#{file}")).should == false
461
1133
  end
462
- @string_io.string.should match /Deleting vm #{@target_vm}/
463
1134
  end
464
1135
 
465
1136
  it 'should delete the target vm metadata' do
466
1137
  Fission::Metadata.should_receive(:delete_vm_info)
467
- Fission::VM.delete @target_vm
1138
+ @vm.delete
1139
+ end
1140
+
1141
+ it 'should return a successful reponsse object' do
1142
+ Fission::Metadata.stub!(:delete_vm_info)
1143
+ @vm.delete.should be_a_successful_response
468
1144
  end
469
1145
 
470
1146
  end