fission 0.4.0 → 0.5.0.beta.1
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.
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +12 -3
- data/README.md +45 -19
- data/bin/fission +1 -1
- data/fission.gemspec +3 -2
- data/lib/fission.rb +15 -0
- data/lib/fission/action/shell_executor.rb +37 -0
- data/lib/fission/action/snapshot/creator.rb +81 -0
- data/lib/fission/action/snapshot/deleter.rb +85 -0
- data/lib/fission/action/snapshot/lister.rb +90 -0
- data/lib/fission/action/snapshot/reverter.rb +81 -0
- data/lib/fission/action/vm/cloner.rb +191 -0
- data/lib/fission/action/vm/deleter.rb +73 -0
- data/lib/fission/action/vm/lister.rb +138 -0
- data/lib/fission/action/vm/starter.rb +88 -0
- data/lib/fission/action/vm/stopper.rb +79 -0
- data/lib/fission/action/vm/suspender.rb +68 -0
- data/lib/fission/cli.rb +21 -117
- data/lib/fission/command.rb +39 -0
- data/lib/fission/command/clone.rb +11 -6
- data/lib/fission/command/delete.rb +11 -6
- data/lib/fission/command/info.rb +62 -0
- data/lib/fission/command/snapshot_create.rb +9 -3
- data/lib/fission/command/snapshot_delete.rb +38 -0
- data/lib/fission/command/snapshot_list.rb +9 -3
- data/lib/fission/command/snapshot_revert.rb +9 -3
- data/lib/fission/command/start.rb +11 -6
- data/lib/fission/command/status.rb +9 -1
- data/lib/fission/command/stop.rb +9 -3
- data/lib/fission/command/suspend.rb +11 -6
- data/lib/fission/command_helpers.rb +18 -4
- data/lib/fission/command_line_parser.rb +189 -0
- data/lib/fission/config.rb +1 -1
- data/lib/fission/fusion.rb +3 -4
- data/lib/fission/lease.rb +2 -1
- data/lib/fission/metadata.rb +6 -1
- data/lib/fission/response.rb +17 -9
- data/lib/fission/version.rb +1 -1
- data/lib/fission/vm.rb +142 -382
- data/lib/fission/vm_configuration.rb +79 -0
- data/spec/fission/action/execute_shell_command_spec.rb +25 -0
- data/spec/fission/action/snapshot/creator_spec.rb +77 -0
- data/spec/fission/action/snapshot/deleter_spec.rb +84 -0
- data/spec/fission/action/snapshot/lister_spec.rb +67 -0
- data/spec/fission/action/snapshot/reverter_spec.rb +76 -0
- data/spec/fission/action/vm/cloner_spec.rb +198 -0
- data/spec/fission/action/vm/deleter_spec.rb +79 -0
- data/spec/fission/action/vm/lister_spec.rb +164 -0
- data/spec/fission/action/vm/starter_spec.rb +88 -0
- data/spec/fission/action/vm/stopper_spec.rb +71 -0
- data/spec/fission/action/vm/suspender_spec.rb +59 -0
- data/spec/fission/cli_spec.rb +32 -157
- data/spec/fission/command/clone_spec.rb +9 -3
- data/spec/fission/command/delete_spec.rb +11 -3
- data/spec/fission/command/info_spec.rb +130 -0
- data/spec/fission/command/snapshot_create_spec.rb +11 -3
- data/spec/fission/command/snapshot_delete_spec.rb +74 -0
- data/spec/fission/command/snapshot_list_spec.rb +11 -3
- data/spec/fission/command/snapshot_revert_spec.rb +11 -3
- data/spec/fission/command/start_spec.rb +11 -3
- data/spec/fission/command/status_spec.rb +16 -5
- data/spec/fission/command/stop_spec.rb +11 -3
- data/spec/fission/command/suspend_spec.rb +11 -3
- data/spec/fission/command_helpers_spec.rb +27 -5
- data/spec/fission/command_line_parser_spec.rb +267 -0
- data/spec/fission/command_spec.rb +16 -1
- data/spec/fission/config_spec.rb +3 -3
- data/spec/fission/fusion_spec.rb +11 -6
- data/spec/fission/lease_spec.rb +81 -45
- data/spec/fission/metadata_spec.rb +29 -6
- data/spec/fission/response_spec.rb +20 -9
- data/spec/fission/ui_spec.rb +1 -1
- data/spec/fission/vm_configuration_spec.rb +132 -0
- data/spec/fission/vm_spec.rb +393 -750
- data/spec/helpers/command_helpers.rb +1 -1
- metadata +93 -15
- data/.rvmrc +0 -1
@@ -0,0 +1,79 @@
|
|
1
|
+
module Fission
|
2
|
+
|
3
|
+
class VMConfiguration
|
4
|
+
|
5
|
+
# Internal: Creates a new VMConfiguration object. This accepts a VM object
|
6
|
+
#
|
7
|
+
# vm - An instance of VM
|
8
|
+
#
|
9
|
+
# Examples:
|
10
|
+
#
|
11
|
+
# Fission::VMConfiguration.new @my_vm
|
12
|
+
#
|
13
|
+
# Returns a new VMConfiguration object
|
14
|
+
def initialize(vm)
|
15
|
+
@vm = vm
|
16
|
+
end
|
17
|
+
|
18
|
+
# Internal: Gathers the the configuration data for the VM. This essentially
|
19
|
+
# parses the key/value pairs from the configuration file (.vmx) into a Hash.
|
20
|
+
#
|
21
|
+
# Exaples:
|
22
|
+
#
|
23
|
+
# @vm_config.config_data.data
|
24
|
+
# # => { 'memsize' => '384', 'ethernet0.present' => 'TRUE',... }
|
25
|
+
#
|
26
|
+
# Returns a Response object with the result.
|
27
|
+
# If successful, the Response's data attribute will be a Hash. All keys and
|
28
|
+
# values are represented as a String (even when the value in the
|
29
|
+
# configuration file is 'TRUE'). If a value is an empty string in the
|
30
|
+
# configuration file, it will be represented in the Hash as an empty String.
|
31
|
+
# If there is an error, an unsuccessful Response will be returned.
|
32
|
+
def config_data
|
33
|
+
return Response.new :code => 1, :message => 'VM does not exist' unless @vm.exists?
|
34
|
+
|
35
|
+
conf_file_response = @vm.conf_file
|
36
|
+
return conf_file_response unless conf_file_response.successful?
|
37
|
+
|
38
|
+
@conf_file_location = conf_file_response.data
|
39
|
+
|
40
|
+
Response.new :code => 0, :data => parse_vm_config_file
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
# Internal: Parses the configuration file (i.e. '.vmx')
|
45
|
+
#
|
46
|
+
# Examples:
|
47
|
+
#
|
48
|
+
# @vm_config.parse_vm_config_file
|
49
|
+
# # => { 'memsize' => '384', 'ethernet0.present' => 'TRUE',... }
|
50
|
+
#
|
51
|
+
# Returns a Hash.
|
52
|
+
# All keys and values are represented as a String (even when the value in
|
53
|
+
# the conf file is 'TRUE'). If a value is an empty string in the
|
54
|
+
# configuration file, it will be represented in the Hash as an empty String.
|
55
|
+
def parse_vm_config_file
|
56
|
+
File.readlines(@conf_file_location).inject({}) do |result, line|
|
57
|
+
data = parse_line_data(line)
|
58
|
+
result[data[0]] = (data[1].nil? ? '' : data[1])
|
59
|
+
result
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Internal: Splits and formats a single line from a VM configuration file
|
64
|
+
# into an Array.
|
65
|
+
#
|
66
|
+
# Examples:
|
67
|
+
#
|
68
|
+
# @vm_config.parse_line_data('foo = "bar"')
|
69
|
+
#
|
70
|
+
# Returns an Array. The first item will be the left side of the '=' and the
|
71
|
+
# second item will be the right side. This will also strip any whitespace
|
72
|
+
# characters from the beginning or end of the provided line.
|
73
|
+
def parse_line_data(line)
|
74
|
+
line.strip.gsub('"', '').split ' = '
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fission::Action::ShellExecutor do
|
4
|
+
|
5
|
+
describe 'execute' do
|
6
|
+
before do
|
7
|
+
@cmd = 'ls /var/log'
|
8
|
+
@executor = Fission::Action::ShellExecutor.new @cmd
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should execute the shell command' do
|
12
|
+
@executor.should_receive(:`).with(@cmd)
|
13
|
+
@executor.execute
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should return a hash of the output and Process::Status object' do
|
17
|
+
result = @executor.execute
|
18
|
+
result['output'].should be_a String
|
19
|
+
result['output'].empty?.should be_false
|
20
|
+
result['process_status'].should be_a Process::Status
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fission::Action::Snapshot::Creator do
|
4
|
+
describe 'create_snapshot' do
|
5
|
+
before do
|
6
|
+
@vm = Fission::VM.new 'foo'
|
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
|
+
@snapshots_response_mock = mock 'snapshots'
|
11
|
+
@running_response_mock = mock 'running?'
|
12
|
+
|
13
|
+
@running_response_mock.stub_as_successful true
|
14
|
+
@conf_file_response_mock.stub_as_successful @conf_file_path
|
15
|
+
@snapshots_response_mock.stub_as_successful []
|
16
|
+
|
17
|
+
@vm.stub(:exists?).and_return(true)
|
18
|
+
@vm.stub(:snapshots).and_return(@snapshots_response_mock)
|
19
|
+
@vm.stub(:running?).and_return(@running_response_mock)
|
20
|
+
@vm.stub(:conf_file).and_return(@conf_file_response_mock)
|
21
|
+
@creator = Fission::Action::Snapshot::Creator.new @vm
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return an unsuccessful response if the vm doesn't exist" do
|
25
|
+
@vm.stub(:exists?).and_return(false)
|
26
|
+
@creator.create_snapshot('snap_1').should be_an_unsuccessful_response 'VM does not exist'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return an unsuccessful response if the vm is not running' do
|
30
|
+
@running_response_mock.stub_as_successful false
|
31
|
+
|
32
|
+
response = @creator.create_snapshot 'snap_1'
|
33
|
+
error_message = 'The VM must be running in order to take a snapshot.'
|
34
|
+
response.should be_an_unsuccessful_response error_message
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should return an unsuccessful response if unable to determine if running' do
|
38
|
+
@running_response_mock.stub_as_unsuccessful
|
39
|
+
@creator.create_snapshot('snap_1').should be_an_unsuccessful_response
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should return an unsuccessful response if unable to figure out the conf file' do
|
43
|
+
@conf_file_response_mock.stub_as_unsuccessful
|
44
|
+
@creator.create_snapshot('snap_1').should be_an_unsuccessful_response
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return a response when creating the snapshot' do
|
48
|
+
executor_mock = mock 'executor'
|
49
|
+
response = stub
|
50
|
+
cmd = "#{@vmrun_cmd} snapshot "
|
51
|
+
cmd << "'#{@conf_file_path}' \"bar\" 2>&1"
|
52
|
+
|
53
|
+
executor_mock.should_receive(:execute).and_return(executor_mock)
|
54
|
+
Fission::Action::ShellExecutor.should_receive(:new).
|
55
|
+
with(cmd).
|
56
|
+
and_return(executor_mock)
|
57
|
+
Fission::Response.should_receive(:from_shell_executor).
|
58
|
+
with(executor_mock).
|
59
|
+
and_return(response)
|
60
|
+
|
61
|
+
@creator.create_snapshot('bar').should == response
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should return an unsuccessful response if the snapshot name is a duplicate' do
|
65
|
+
@snapshots_response_mock.stub_as_successful ['snap_1']
|
66
|
+
response = @creator.create_snapshot 'snap_1'
|
67
|
+
response.should be_an_unsuccessful_response "There is already a snapshot named 'snap_1'."
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should return an unsuccessful response if there was a problem listing the existing snapshots' do
|
71
|
+
@snapshots_response_mock.stub_as_unsuccessful
|
72
|
+
@creator.create_snapshot('snap_1').should be_an_unsuccessful_response
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fission::Action::Snapshot::Deleter do
|
4
|
+
|
5
|
+
describe 'delete_snapshot' do
|
6
|
+
before do
|
7
|
+
@vm = Fission::VM.new 'foo'
|
8
|
+
@conf_file_path = File.join @vm.path, 'foo.vmx'
|
9
|
+
@vmrun_cmd = Fission.config['vmrun_cmd']
|
10
|
+
@conf_file_response_mock = mock 'conf_file_response'
|
11
|
+
@snapshots_response_mock = mock 'snapshots'
|
12
|
+
@running_response_mock = mock 'running?'
|
13
|
+
|
14
|
+
@running_response_mock.stub_as_successful true
|
15
|
+
@conf_file_response_mock.stub_as_successful @conf_file_path
|
16
|
+
@snapshots_response_mock.stub_as_successful ['snap_1']
|
17
|
+
|
18
|
+
@vm.stub(:exists?).and_return(true)
|
19
|
+
@vm.stub(:snapshots).and_return(@snapshots_response_mock)
|
20
|
+
@vm.stub(:running?).and_return(@running_response_mock)
|
21
|
+
@vm.stub(:conf_file).and_return(@conf_file_response_mock)
|
22
|
+
Fission::Fusion.stub(:running?).and_return(false)
|
23
|
+
@deleter = Fission::Action::Snapshot::Deleter.new @vm
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return an unsuccessful response if the vm doesn't exist" do
|
27
|
+
@vm.stub(:exists?).and_return(false)
|
28
|
+
@deleter.delete_snapshot('snap_1').should be_an_unsuccessful_response 'VM does not exist'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should return an unsuccessful response if unable to figure out the conf file' do
|
32
|
+
@conf_file_response_mock.stub_as_unsuccessful
|
33
|
+
@deleter.delete_snapshot('snap_1').should be_an_unsuccessful_response
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should return an unsuccessful response if the snapshot does not exist' do
|
37
|
+
@snapshots_response_mock.stub_as_successful []
|
38
|
+
response = @deleter.delete_snapshot 'snap_1'
|
39
|
+
response.should be_an_unsuccessful_response "Unable to find a snapshot named 'snap_1'."
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should return an unsuccessful response if there was a problem listing the existing snapshots' do
|
43
|
+
@snapshots_response_mock.stub_as_unsuccessful
|
44
|
+
@deleter.delete_snapshot('snap_1').should be_an_unsuccessful_response
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should return a response when deleting the snapshot' do
|
48
|
+
executor_mock = mock 'executor'
|
49
|
+
response = stub
|
50
|
+
cmd = "#{@vmrun_cmd} deleteSnapshot "
|
51
|
+
cmd << "'#{@conf_file_path}' \"snap_1\" 2>&1"
|
52
|
+
|
53
|
+
executor_mock.should_receive(:execute).and_return(executor_mock)
|
54
|
+
Fission::Action::ShellExecutor.should_receive(:new).
|
55
|
+
with(cmd).
|
56
|
+
and_return(executor_mock)
|
57
|
+
Fission::Response.should_receive(:from_shell_executor).
|
58
|
+
with(executor_mock).
|
59
|
+
and_return(response)
|
60
|
+
|
61
|
+
@deleter.delete_snapshot('snap_1').should == response
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when the gui is running' do
|
65
|
+
before do
|
66
|
+
Fission::Fusion.stub(:running?).and_return(true)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return an unsuccessful response if the vm is not running' do
|
70
|
+
@running_response_mock.stub_as_successful false
|
71
|
+
response = @deleter.delete_snapshot 'snap_1'
|
72
|
+
error_message = 'A snapshot cannot be deleted when the GUI is running and the VM is not running.'
|
73
|
+
response.should be_an_unsuccessful_response error_message
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should return an unsuccessful response if unable to determine if running' do
|
77
|
+
@running_response_mock.stub_as_unsuccessful
|
78
|
+
@deleter.delete_snapshot('snap_1').should be_an_unsuccessful_response
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fission::Action::Snapshot::Lister do
|
4
|
+
before do
|
5
|
+
@vm = Fission::VM.new 'foo'
|
6
|
+
@conf_file_path = File.join @vm.path, 'foo.vmx'
|
7
|
+
@vmrun_cmd = Fission.config['vmrun_cmd']
|
8
|
+
@conf_file_response_mock = mock 'conf_file_response'
|
9
|
+
@vm.stub(:conf_file).and_return(@conf_file_response_mock)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'snapshots' do
|
13
|
+
before do
|
14
|
+
@vm.stub(:exists?).and_return(true)
|
15
|
+
@conf_file_response_mock.stub_as_successful @conf_file_path
|
16
|
+
@lister = Fission::Action::Snapshot::Lister.new @vm
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return an unsuccessful repsonse when the vm doesn't exist" do
|
20
|
+
@vm.stub(:exists?).and_return(false)
|
21
|
+
@lister.snapshots.should be_an_unsuccessful_response 'VM does not exist'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should return an unsuccessful response if unable to figure out the conf file' do
|
25
|
+
@conf_file_response_mock.stub_as_unsuccessful
|
26
|
+
@lister.snapshots.should be_an_unsuccessful_response
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return a response when listing the snapshots' do
|
30
|
+
executor_mock = mock 'executor'
|
31
|
+
process_mock = stub :exitstatus => 0
|
32
|
+
cmd = "#{@vmrun_cmd} listSnapshots "
|
33
|
+
cmd << "'#{@conf_file_path}' 2>&1"
|
34
|
+
|
35
|
+
output_text = "Total snapshots: 3\nsnap foo\nsnap bar\nsnap baz\n"
|
36
|
+
executor_mock.should_receive(:execute).
|
37
|
+
and_return({'output' => output_text,
|
38
|
+
'process_status' => process_mock})
|
39
|
+
|
40
|
+
Fission::Action::ShellExecutor.should_receive(:new).
|
41
|
+
with(cmd).
|
42
|
+
and_return(executor_mock)
|
43
|
+
|
44
|
+
response = @lister.snapshots
|
45
|
+
response.should be_a_successful_response
|
46
|
+
response.data.should == ['snap foo', 'snap bar', 'snap baz']
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return an unsuccessful response if there was a problem listing the snapshots' do
|
50
|
+
executor_mock = mock 'executor'
|
51
|
+
process_mock = stub :exitstatus => 1
|
52
|
+
cmd = "#{@vmrun_cmd} listSnapshots "
|
53
|
+
cmd << "'#{@conf_file_path}' 2>&1"
|
54
|
+
|
55
|
+
executor_mock.should_receive(:execute).
|
56
|
+
and_return({'output' => 'it blew up',
|
57
|
+
'process_status' => process_mock})
|
58
|
+
|
59
|
+
Fission::Action::ShellExecutor.should_receive(:new).
|
60
|
+
with(cmd).
|
61
|
+
and_return(executor_mock)
|
62
|
+
|
63
|
+
@lister.snapshots.should be_an_unsuccessful_response
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fission::Action::Snapshot::Reverter do
|
4
|
+
|
5
|
+
describe 'revert_snapshot' do
|
6
|
+
before do
|
7
|
+
@vm = Fission::VM.new 'foo'
|
8
|
+
@conf_file_path = File.join @vm.path, 'foo.vmx'
|
9
|
+
@vmrun_cmd = Fission.config['vmrun_cmd']
|
10
|
+
@conf_file_response_mock = mock 'conf_file_response'
|
11
|
+
@snapshots_response_mock = mock 'snapshots'
|
12
|
+
|
13
|
+
@conf_file_response_mock.stub_as_successful @conf_file_path
|
14
|
+
@snapshots_response_mock.stub_as_successful []
|
15
|
+
|
16
|
+
@vm.stub(:exists?).and_return(true)
|
17
|
+
@vm.stub(:snapshots).and_return(@snapshots_response_mock)
|
18
|
+
@vm.stub(:conf_file).and_return(@conf_file_response_mock)
|
19
|
+
@snapshots_response_mock.stub_as_successful ['snap_1']
|
20
|
+
Fission::Fusion.stub(:running?).and_return(false)
|
21
|
+
@reverter = Fission::Action::Snapshot::Reverter.new @vm
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return an unsuccessful response if the vm doesn't exist" do
|
25
|
+
@vm.stub(:exists?).and_return(false)
|
26
|
+
@reverter.revert_to_snapshot('snap_1').should be_an_unsuccessful_response 'VM does not exist'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should return an unsuccessful response if the Fusion GUI is running' do
|
30
|
+
Fission::Fusion.stub(:running?).and_return(true)
|
31
|
+
|
32
|
+
response = @reverter.revert_to_snapshot 'snap_1'
|
33
|
+
|
34
|
+
error_string = 'It looks like the Fusion GUI is currently running. '
|
35
|
+
error_string << 'A VM cannot be reverted to a snapshot when the Fusion GUI is running.'
|
36
|
+
error_string << ' Exit the Fusion GUI and try again.'
|
37
|
+
|
38
|
+
response.should be_an_unsuccessful_response error_string
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should return an unsuccessful response if unable to figure out the conf file' do
|
42
|
+
@conf_file_response_mock.stub_as_unsuccessful
|
43
|
+
@reverter.revert_to_snapshot('snap_1').should be_an_unsuccessful_response
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should return a response when reverting to the snapshot' do
|
47
|
+
executor_mock = mock 'executor'
|
48
|
+
response = stub
|
49
|
+
cmd = "#{@vmrun_cmd} revertToSnapshot "
|
50
|
+
cmd << "'#{@conf_file_path}' \"snap_1\" 2>&1"
|
51
|
+
|
52
|
+
executor_mock.should_receive(:execute).and_return(executor_mock)
|
53
|
+
Fission::Action::ShellExecutor.should_receive(:new).
|
54
|
+
with(cmd).
|
55
|
+
and_return(executor_mock)
|
56
|
+
Fission::Response.should_receive(:from_shell_executor).
|
57
|
+
with(executor_mock).
|
58
|
+
and_return(response)
|
59
|
+
|
60
|
+
@reverter.revert_to_snapshot('snap_1').should == response
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should return an unsuccessful response if the snapshot cannot be found' do
|
64
|
+
@snapshots_response_mock.stub_as_successful []
|
65
|
+
response = @reverter.revert_to_snapshot 'snap_1'
|
66
|
+
response.should be_an_unsuccessful_response "Unable to find a snapshot named 'snap_1'."
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return an unsuccessful response if unable to list the existing snapshots' do
|
70
|
+
@snapshots_response_mock.stub_as_unsuccessful
|
71
|
+
@reverter.revert_to_snapshot('snap_1').should be_an_unsuccessful_response
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Fission::Action::VM::Cloner do
|
4
|
+
|
5
|
+
describe 'clone' do
|
6
|
+
before do
|
7
|
+
@source_vm = Fission::VM.new 'foo'
|
8
|
+
@target_vm = Fission::VM.new 'bar'
|
9
|
+
@source_path = @source_vm.path
|
10
|
+
@target_path = @target_vm.path
|
11
|
+
|
12
|
+
@clone_response_mock = mock('clone_response')
|
13
|
+
@vm_files = ['.vmx', '.vmxf', '.vmdk', '-s001.vmdk', '-s002.vmdk', '.vmsd']
|
14
|
+
|
15
|
+
FakeFS.activate!
|
16
|
+
|
17
|
+
FileUtils.mkdir_p @source_path
|
18
|
+
|
19
|
+
@vm_files.each do |file|
|
20
|
+
FileUtils.touch "#{@source_path}/#{@source_vm.name}#{file}"
|
21
|
+
end
|
22
|
+
|
23
|
+
['.vmx', '.vmxf', '.vmdk'].each do |ext|
|
24
|
+
File.open("#{@source_path}/foo#{ext}", 'w') { |f| f.write 'foo.vmdk'}
|
25
|
+
end
|
26
|
+
|
27
|
+
@source_vm.stub(:exists?).and_return(true)
|
28
|
+
@target_vm.stub(:exists?).and_return(false)
|
29
|
+
|
30
|
+
Fission::VM.stub(:new).with(@source_vm.name).
|
31
|
+
and_return(@source_vm)
|
32
|
+
Fission::VM.stub(:new).with(@target_vm.name).
|
33
|
+
and_return(@target_vm)
|
34
|
+
|
35
|
+
vmx_content = 'ide1:0.deviceType = "cdrom-image"
|
36
|
+
nvram = "foo.nvram"
|
37
|
+
ethernet0.present = "TRUE"
|
38
|
+
ethernet1.address = "00:0c:29:1d:6a:75"
|
39
|
+
ethernet0.connectionType = "nat"
|
40
|
+
ethernet0.generatedAddress = "00:0c:29:1d:6a:64"
|
41
|
+
ethernet0.virtualDev = "e1000"
|
42
|
+
tools.remindInstall = "TRUE"
|
43
|
+
ethernet0.wakeOnPcktRcv = "FALSE"
|
44
|
+
ethernet0.addressType = "generated"
|
45
|
+
uuid.action = "keep"
|
46
|
+
ethernet0.linkStatePropagation.enable = "TRUE"
|
47
|
+
ethernet0.generatedAddressenable = "TRUE"
|
48
|
+
ethernet1.generatedAddressenable = "TRUE"'
|
49
|
+
|
50
|
+
File.open("#{@source_path}/#{@source_vm.name}.vmx", 'w') do |f|
|
51
|
+
f.write vmx_content
|
52
|
+
end
|
53
|
+
|
54
|
+
['.vmx', '.vmxf'].each do |ext|
|
55
|
+
File.stub(:binary?).
|
56
|
+
with("#{@target_path}/#{@target_vm.name}#{ext}").
|
57
|
+
and_return(false)
|
58
|
+
end
|
59
|
+
|
60
|
+
File.stub(:binary?).
|
61
|
+
with("#{@target_path}/#{@target_vm.name}.vmdk").
|
62
|
+
and_return(true)
|
63
|
+
@cloner = Fission::Action::VM::Cloner.new @source_vm, @target_vm
|
64
|
+
end
|
65
|
+
|
66
|
+
after do
|
67
|
+
FakeFS.deactivate!
|
68
|
+
FakeFS::FileSystem.clear
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should return an unsuccessful response if the source vm doesn't exist" do
|
72
|
+
@source_vm.stub(:exists?).and_return(false)
|
73
|
+
response = @cloner.clone
|
74
|
+
response.should be_an_unsuccessful_response 'VM does not exist'
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return an unsuccessful response if the target vm exists" do
|
78
|
+
@target_vm.stub(:exists?).and_return(true)
|
79
|
+
response = @cloner.clone
|
80
|
+
response.should be_an_unsuccessful_response 'VM already exists'
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should copy the vm files to the target' do
|
84
|
+
@cloner.clone
|
85
|
+
|
86
|
+
File.directory?(@target_path).should == true
|
87
|
+
|
88
|
+
@vm_files.each do |file|
|
89
|
+
File.file?("#{@target_path}/bar#{file}").should == true
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should copy the vm files to the target if a file name doesn't match the directory" do
|
94
|
+
FileUtils.touch "#{@source_path}/other_name.nvram"
|
95
|
+
|
96
|
+
@cloner.clone
|
97
|
+
|
98
|
+
File.directory?(@target_path).should == true
|
99
|
+
|
100
|
+
@vm_files.each do |file|
|
101
|
+
File.file?("#{@target_path}/#{@target_vm.name}#{file}").should == true
|
102
|
+
end
|
103
|
+
|
104
|
+
File.file?("#{@target_path}/bar.nvram").should == true
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should copy the vm files to the target if a sparse disk file name doesn't match the directory" do
|
108
|
+
FileUtils.touch "#{@source_path}/other_name-s003.vmdk"
|
109
|
+
|
110
|
+
@cloner.clone
|
111
|
+
|
112
|
+
File.directory?(@target_path).should == true
|
113
|
+
|
114
|
+
@vm_files.each do |file|
|
115
|
+
File.file?("#{@target_path}/#{@target_vm.name}#{file}").should == true
|
116
|
+
end
|
117
|
+
|
118
|
+
File.file?("#{@target_path}/bar-s003.vmdk").should == true
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'should update the target vm config files' do
|
122
|
+
@cloner.clone
|
123
|
+
|
124
|
+
['.vmx', '.vmxf'].each do |ext|
|
125
|
+
File.read("#{@target_path}/bar#{ext}").should_not match /foo/
|
126
|
+
File.read("#{@target_path}/bar#{ext}").should match /bar/
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should disable VMware tools warning in the conf file' do
|
131
|
+
@cloner.clone
|
132
|
+
pattern = /^tools\.remindInstall = "FALSE"/
|
133
|
+
File.read("#{@target_path}/bar.vmx").should match pattern
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should remove auto generated MAC addresses from the conf file' do
|
137
|
+
@cloner.clone
|
138
|
+
pattern = /^ethernet\.+generatedAddress.+/
|
139
|
+
File.read("#{@target_path}/bar.vmx").should_not match pattern
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should setup the conf file to generate a new uuid' do
|
143
|
+
@cloner.clone
|
144
|
+
pattern = /^uuid\.action = "create"/
|
145
|
+
File.read("#{@target_path}/bar.vmx").scan(pattern).count.should == 1
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'when uuid.action already exists in the source conf file' do
|
149
|
+
before do
|
150
|
+
File.open("#{@source_path}/#{@source_vm.name}.vmx", 'a') do |f|
|
151
|
+
f.write "\nuuid.action = \"create\""
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should not add another entry for uuid.action' do
|
156
|
+
@cloner.clone
|
157
|
+
pattern = /^uuid\.action = "create"/
|
158
|
+
File.read("#{@target_path}/bar.vmx").scan(pattern).count.should == 1
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'when tools.remindInstall already exists in the source conf file' do
|
163
|
+
before do
|
164
|
+
File.open("#{@source_path}/#{@source_vm.name}.vmx", 'w') do |f|
|
165
|
+
f.write "\ntools.remindInstall = \"FALSE\""
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should not add another entry for tools.remindInstall' do
|
170
|
+
@cloner.clone
|
171
|
+
pattern = /^tools\.remindInstall = "FALSE"/
|
172
|
+
File.read("#{@target_path}/bar.vmx").scan(pattern).count.should == 1
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should not try to update the vmdk file if it's not a sparse disk" do
|
177
|
+
@cloner.clone
|
178
|
+
File.read("#{@target_path}/bar.vmdk").should match /foo/
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should return a successful response if clone was successful' do
|
182
|
+
@cloner.clone.should be_a_successful_response
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'when a sparse disk is found' do
|
186
|
+
it "should update the vmdk" do
|
187
|
+
File.rspec_reset
|
188
|
+
File.stub(:binary?).and_return(false)
|
189
|
+
|
190
|
+
@cloner.clone
|
191
|
+
|
192
|
+
File.read("#{@target_path}/bar.vmdk").should match /bar/
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|