fission 0.2.0 → 0.3.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,13 +7,13 @@ module Fission
7
7
  end
8
8
 
9
9
  def execute
10
- unless args.count == 1
10
+ unless @args.count == 1
11
11
  Fission.ui.output self.class.help
12
12
  Fission.ui.output ""
13
13
  Fission.ui.output_and_exit "Incorrect arguments for stop command", 1
14
14
  end
15
15
 
16
- vm_name = args.first
16
+ vm_name = @args.first
17
17
 
18
18
  unless Fission::VM.exists? vm_name
19
19
  Fission.ui.output_and_exit "Unable to find the VM #{vm_name} (#{Fission::VM.path(vm_name)})", 1
@@ -4,34 +4,50 @@ module Fission
4
4
 
5
5
  def initialize(args=[])
6
6
  super
7
+ @options.all = false
7
8
  end
8
9
 
9
10
  def execute
10
- unless args.count == 1
11
+ option_parser.parse! @args
12
+
13
+ if @args.count != 1 && !@options.all
11
14
  Fission.ui.output self.class.help
12
15
  Fission.ui.output ""
13
16
  Fission.ui.output_and_exit "Incorrect arguments for suspend command", 1
14
17
  end
15
18
 
16
- vm_name = args.first
17
-
18
- unless Fission::VM.exists? vm_name
19
- Fission.ui.output_and_exit "Unable to find the VM #{vm_name} (#{Fission::VM.path(vm_name)})", 1
19
+ vms_to_suspend.each do |vm_name|
20
+ Fission.ui.output "Suspending '#{vm_name}'"
21
+ Fission::VM.new(vm_name).suspend
20
22
  end
23
+ end
21
24
 
22
- unless VM.all_running.include?(vm_name)
23
- Fission.ui.output ''
24
- Fission.ui.output_and_exit "VM '#{vm_name}' is not running", 0
25
+ def vms_to_suspend
26
+ if @options.all
27
+ vms_to_suspend = VM.all_running
28
+ else
29
+ vm_name = @args.first
30
+ unless Fission::VM.exists? vm_name
31
+ Fission.ui.output ''
32
+ Fission.ui.output_and_exit "Unable to find the VM #{vm_name} (#{Fission::VM.path(vm_name)})", 1
33
+ end
34
+
35
+ unless VM.all_running.include?(vm_name)
36
+ Fission.ui.output ''
37
+ Fission.ui.output_and_exit "VM '#{vm_name}' is not running", 1
38
+ end
39
+
40
+ vms_to_suspend = [vm_name]
25
41
  end
26
-
27
- Fission.ui.output "suspending '#{vm_name}'"
28
- @vm = Fission::VM.new vm_name
29
- @vm.suspend
30
42
  end
31
43
 
32
44
  def option_parser
33
45
  optparse = OptionParser.new do |opts|
34
- opts.banner = "\nsuspend usage: fission suspend vm"
46
+ opts.banner = "\nsuspend usage: fission suspend [vm | --all]"
47
+
48
+ opts.on '--all', 'Suspend all running VMs' do
49
+ @options.all = true
50
+ end
35
51
  end
36
52
 
37
53
  optparse
@@ -14,6 +14,8 @@ module Fission
14
14
 
15
15
  @attributes['vmrun_bin'] = '/Library/Application Support/VMware Fusion/vmrun'
16
16
  @attributes['vmrun_cmd'] = "#{@attributes['vmrun_bin'].gsub(' ', '\ ')} -T fusion"
17
+ @attributes['plist_file'] = File.expand_path('~/Library/Preferences/com.vmware.fusion.plist')
18
+ @attributes['gui_bin'] = File.expand_path('/Applications/VMware Fusion.app/Contents/MacOS/vmware')
17
19
  end
18
20
 
19
21
  private
@@ -0,0 +1,13 @@
1
+ module Fission
2
+ class Fusion
3
+
4
+ def self.is_running?
5
+ command = "ps -ef | grep -v grep | grep -c "
6
+ command << "#{Fission.config.attributes['gui_bin'].gsub(' ', '\ ')} 2>&1"
7
+ output = `#{command}`
8
+
9
+ output.strip.to_i > 0 ? true : false
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ module Fission
2
+ class Metadata
3
+
4
+ require 'cfpropertylist'
5
+
6
+ attr_accessor :content
7
+
8
+ def self.delete_vm_info(vm_path)
9
+ metadata = new
10
+ metadata.load
11
+ metadata.delete_vm_restart_document(vm_path)
12
+ metadata.delete_vm_favorite_entry(vm_path)
13
+ metadata.save
14
+ end
15
+
16
+ def load
17
+ raw_data = CFPropertyList::List.new :file => Fission.config.attributes['plist_file']
18
+ @content = CFPropertyList.native_types raw_data.value
19
+ end
20
+
21
+ def save
22
+ new_content = CFPropertyList::List.new
23
+ new_content.value = CFPropertyList.guess @content
24
+ new_content.save Fission.config.attributes['plist_file'],
25
+ CFPropertyList::List::FORMAT_BINARY
26
+ end
27
+
28
+ def delete_vm_restart_document(vm_path)
29
+ if @content.has_key?('PLRestartDocumentPaths')
30
+ @content['PLRestartDocumentPaths'].delete_if { |p| p == vm_path }
31
+ end
32
+ end
33
+
34
+ def delete_vm_favorite_entry(vm_path)
35
+ @content['VMFavoritesListDefaults2'].delete_if { |vm| vm['path'] == vm_path }
36
+ end
37
+
38
+ end
39
+ end
@@ -1,3 +1,3 @@
1
1
  module Fission
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0.beta.1"
3
3
  end
@@ -6,8 +6,52 @@ module Fission
6
6
  @name = name
7
7
  end
8
8
 
9
- def start
10
- command = "#{Fission.config.attributes['vmrun_cmd']} start #{conf_file.gsub ' ', '\ '} gui 2>&1"
9
+ def create_snapshot(name)
10
+ command = "#{Fission.config.attributes['vmrun_cmd']} snapshot #{conf_file.gsub ' ', '\ '} \"#{name}\" 2>&1"
11
+ output = `#{command}`
12
+
13
+ if $?.exitstatus == 0
14
+ Fission.ui.output "Snapshot '#{name}' created"
15
+ else
16
+ Fission.ui.output "There was an error creating the snapshot."
17
+ Fission.ui.output_and_exit "The error was:\n#{output}", 1
18
+ end
19
+ end
20
+
21
+ def revert_to_snapshot(name)
22
+ command = "#{Fission.config.attributes['vmrun_cmd']} revertToSnapshot #{conf_file.gsub ' ', '\ '} \"#{name}\" 2>&1"
23
+ output = `#{command}`
24
+
25
+ if $?.exitstatus == 0
26
+ Fission.ui.output "Reverted to snapshot '#{name}'"
27
+ else
28
+ Fission.ui.output "There was an error reverting to the snapshot."
29
+ Fission.ui.output_and_exit "The error was:\n#{output}", 1
30
+ end
31
+ end
32
+
33
+ def snapshots
34
+ command = "#{Fission.config.attributes['vmrun_cmd']} listSnapshots #{conf_file.gsub ' ', '\ '} 2>&1"
35
+ output = `#{command}`
36
+
37
+ if $?.exitstatus == 0
38
+ snaps = output.split("\n").select { |s| !s.include? 'Total snapshots:' }
39
+ snaps.map { |s| s.strip }
40
+ else
41
+ Fission.ui.output "There was an error getting the list of snapshots."
42
+ Fission.ui.output_and_exit "The error was:\n#{output}", 1
43
+ end
44
+ end
45
+
46
+ def start(args={})
47
+ command = "#{Fission.config.attributes['vmrun_cmd']} start #{conf_file.gsub ' ', '\ '} "
48
+
49
+ if !args[:headless].blank? && args[:headless]
50
+ command << "nogui 2>&1"
51
+ else
52
+ command << "gui 2>&1"
53
+ end
54
+
11
55
  output = `#{command}`
12
56
 
13
57
  if $?.exitstatus == 0
@@ -40,7 +84,24 @@ module Fission
40
84
  end
41
85
 
42
86
  def conf_file
43
- File.join self.class.path(@name), "#{@name}.vmx"
87
+ vmx_path = File.join(self.class.path(@name), "*.vmx")
88
+ conf_files = Dir.glob(vmx_path)
89
+
90
+ case conf_files.count
91
+ when 0
92
+ Fission.ui.output_and_exit "Unable to find a config file for VM '#{@name}' (in '#{vmx_path}')", 1
93
+ when 1
94
+ conf_files.first
95
+ else
96
+ if conf_files.include?(File.join(File.dirname(vmx_path), "#{@name}.vmx"))
97
+ File.join(File.dirname(vmx_path), "#{@name}.vmx")
98
+ else
99
+ output = "Multiple config files found for VM '#{@name}' ("
100
+ output << conf_files.sort.map { |f| "'#{File.basename(f)}'" }.join(', ')
101
+ output << " in '#{File.dirname(vmx_path)}')"
102
+ Fission.ui.output_and_exit output, 1
103
+ end
104
+ end
44
105
  end
45
106
 
46
107
  def self.all
@@ -56,21 +117,15 @@ module Fission
56
117
 
57
118
  output = `#{command}`
58
119
 
59
- vms = []
60
-
61
120
  if $?.exitstatus == 0
62
- output.split("\n").each do |vm|
63
- if vm.include?('.vmx')
64
- if File.exists?(vm) && (File.extname(vm) == '.vmx')
65
- vms << File.basename(vm, '.vmx')
66
- end
67
- end
121
+ vms = output.split("\n").select do |vm|
122
+ vm.include?('.vmx') && File.exists?(vm) && File.extname(vm) == '.vmx'
68
123
  end
124
+
125
+ vms.map { |vm| File.basename(File.dirname(vm), '.vmwarevm') }
69
126
  else
70
127
  Fission.ui.output_and_exit "Unable to determine the list of running VMs", 1
71
128
  end
72
-
73
- vms
74
129
  end
75
130
 
76
131
  def self.exists?(vm_name)
@@ -90,15 +145,45 @@ module Fission
90
145
  update_config source_vm, target_vm
91
146
  end
92
147
 
148
+ def self.delete(vm_name)
149
+ Fission.ui.output "Deleting vm #{vm_name}"
150
+ FileUtils.rm_rf path(vm_name)
151
+ Fission::Metadata.delete_vm_info(path(vm_name))
152
+ end
153
+
93
154
  private
94
155
  def self.rename_vm_files(from, to)
95
156
  files_to_rename(from, to).each do |file|
96
- FileUtils.mv File.join(path(to), file), File.join(path(to), file.gsub(from, to))
157
+ text_to_replace = File.basename(file, File.extname(file))
158
+
159
+ if File.extname(file) == '.vmdk'
160
+ if file.match /\-s\d+\.vmdk/
161
+ text_to_replace = file.partition(/\-s\d+.vmdk/).first
162
+ end
163
+ end
164
+
165
+ unless File.exists?(File.join(path(to), file.gsub(text_to_replace, to)))
166
+ FileUtils.mv File.join(path(to), file),
167
+ File.join(path(to), file.gsub(text_to_replace, to))
168
+ end
97
169
  end
98
170
  end
99
171
 
100
172
  def self.files_to_rename(from, to)
101
- Dir.entries(path(to)).select { |f| f.include?(from) }
173
+ files_which_match_source_vm = []
174
+ other_files = []
175
+
176
+ Dir.entries(path(to)).each do |f|
177
+ unless f == '.' || f == '..'
178
+ f.include?(from) ? files_which_match_source_vm << f : other_files << f
179
+ end
180
+ end
181
+
182
+ files_which_match_source_vm + other_files
183
+ end
184
+
185
+ def self.vm_file_extensions
186
+ ['.nvram', '.vmdk', '.vmem', '.vmsd', '.vmss', '.vmx', '.vmxf']
102
187
  end
103
188
 
104
189
  def self.update_config(from, to)
@@ -1,19 +1,20 @@
1
1
  require File.expand_path('../../spec_helper.rb', __FILE__)
2
2
 
3
3
  describe Fission::CLI do
4
- before :each do
4
+ before do
5
5
  @string_io = StringIO.new
6
6
  Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
7
7
  end
8
8
 
9
9
  describe 'self.commands' do
10
10
  it 'should return the list of commands' do
11
- Fission::CLI.commands.should == ['clone', 'start', 'status', 'stop', 'suspend']
11
+ Fission::CLI.commands.should == ['clone', 'delete', 'snapshot create',
12
+ 'snapshot list', 'snapshot revert',
13
+ 'start', 'status', 'stop', 'suspend']
12
14
  end
13
15
  end
14
16
 
15
17
  describe 'execute' do
16
-
17
18
  describe 'with no arguments' do
18
19
  it 'should output the usage info' do
19
20
  lambda {
@@ -35,7 +36,6 @@ describe Fission::CLI do
35
36
 
36
37
  end
37
38
  end
38
-
39
39
  end
40
40
 
41
41
  describe '-h or --help' do
@@ -48,11 +48,10 @@ describe Fission::CLI do
48
48
  @string_io.string.should match /Usage/
49
49
  end
50
50
  end
51
-
52
51
  end
53
52
 
54
53
  describe 'with the sub command' do
55
- before :each do
54
+ before do
56
55
  @cmd_mock = mock('cmd')
57
56
  @cmd_mock.should_receive(:execute)
58
57
  end
@@ -60,23 +59,74 @@ describe Fission::CLI do
60
59
  describe 'clone' do
61
60
  it "should try to clone the vm" do
62
61
  Fission::Command::Clone.stub!(:help).and_return('')
63
- Fission::Command::Clone.should_receive(:new).with(['foo', 'bar']).and_return(@cmd_mock)
62
+ Fission::Command::Clone.should_receive(:new).with(['foo', 'bar']).
63
+ and_return(@cmd_mock)
64
64
  Fission::CLI.execute ['clone', 'foo', 'bar']
65
65
  end
66
+
67
+ it 'should try to clone the vm and start it' do
68
+ Fission::Command::Clone.stub!(:help).and_return('')
69
+ Fission::Command::Clone.should_receive(:new).with(['foo', 'bar', '--start']).
70
+ and_return(@cmd_mock)
71
+ Fission::CLI.execute ['clone', 'foo', 'bar', '--start']
72
+ end
73
+ end
74
+
75
+ describe 'snapshot create' do
76
+ it "should create a snapshot" do
77
+ Fission::Command::SnapshotCreate.stub!(:help).and_return('')
78
+ Fission::Command::SnapshotCreate.should_receive(:new).
79
+ with(['foo', 'snap1']).
80
+ and_return(@cmd_mock)
81
+ Fission::CLI.execute ['snapshot', 'create', 'foo', 'snap1']
82
+ end
83
+ end
84
+
85
+ describe 'snapshot list' do
86
+ it "should list the snapshots" do
87
+ Fission::Command::SnapshotList.stub!(:help).and_return('')
88
+ Fission::Command::SnapshotList.should_receive(:new).
89
+ with([]).
90
+ and_return(@cmd_mock)
91
+ Fission::CLI.execute ['snapshot', 'list']
92
+ end
93
+ end
94
+
95
+ describe 'snapshot revert' do
96
+ it "should revert to the snapshots" do
97
+ Fission::Command::SnapshotRevert.stub!(:help).and_return('')
98
+ Fission::Command::SnapshotRevert.should_receive(:new).
99
+ with(['foo', 'snap1']).
100
+ and_return(@cmd_mock)
101
+ Fission::CLI.execute ['snapshot', 'revert', 'foo', 'snap1']
102
+ end
66
103
  end
67
104
 
68
105
  describe 'start' do
69
106
  it "should try to start the vm" do
70
107
  Fission::Command::Start.stub!(:help).and_return('')
71
- Fission::Command::Start.should_receive(:new).with(['foo']).and_return(@cmd_mock)
108
+ Fission::Command::Start.should_receive(:new).
109
+ with(['foo']).
110
+ and_return(@cmd_mock)
72
111
  Fission::CLI.execute ['start', 'foo']
73
112
  end
113
+
114
+ it 'should try to start the vm headless' do
115
+ Fission::Command::Start.stub!(:help).and_return('')
116
+ Fission::Command::Start.should_receive(:new).
117
+ with(['foo', '--headless']).
118
+ and_return(@cmd_mock)
119
+ Fission::CLI.execute ['start', 'foo', '--headless']
120
+
121
+ end
74
122
  end
75
123
 
76
124
  describe 'status' do
77
125
  it "should try to get the status for all VMs" do
78
126
  Fission::Command::Status.stub!(:help).and_return('')
79
- Fission::Command::Status.should_receive(:new).and_return(@cmd_mock)
127
+ Fission::Command::Status.should_receive(:new).
128
+ with([]).
129
+ and_return(@cmd_mock)
80
130
  Fission::CLI.execute ['status']
81
131
  end
82
132
  end
@@ -84,7 +134,9 @@ describe Fission::CLI do
84
134
  describe 'stop' do
85
135
  it "should try to stop the vm" do
86
136
  Fission::Command::Stop.stub!(:help).and_return('')
87
- Fission::Command::Stop.should_receive(:new).with(['foo']).and_return(@cmd_mock)
137
+ Fission::Command::Stop.should_receive(:new).
138
+ with(['foo']).
139
+ and_return(@cmd_mock)
88
140
  Fission::CLI.execute ['stop', 'foo']
89
141
  end
90
142
  end
@@ -92,9 +144,37 @@ describe Fission::CLI do
92
144
  describe 'suspend' do
93
145
  it "should try to suspend the vm" do
94
146
  Fission::Command::Suspend.stub!(:help).and_return('')
95
- Fission::Command::Suspend.should_receive(:new).with(['foo']).and_return(@cmd_mock)
147
+ Fission::Command::Suspend.should_receive(:new).
148
+ with(['foo']).
149
+ and_return(@cmd_mock)
96
150
  Fission::CLI.execute ['suspend', 'foo']
97
151
  end
152
+
153
+ it 'should try to suspend all of vms' do
154
+ Fission::Command::Suspend.stub!(:help).and_return('')
155
+ Fission::Command::Suspend.should_receive(:new).
156
+ with(['--all']).
157
+ and_return(@cmd_mock)
158
+ Fission::CLI.execute ['suspend', '--all']
159
+ end
160
+ end
161
+
162
+ describe 'delete' do
163
+ it "should try to delete the vm" do
164
+ Fission::Command::Delete.stub!(:help).and_return('')
165
+ Fission::Command::Delete.should_receive(:new).
166
+ with(['foo']).
167
+ and_return(@cmd_mock)
168
+ Fission::CLI.execute ['delete', 'foo']
169
+ end
170
+
171
+ it 'should try to force delete the vm' do
172
+ Fission::Command::Delete.stub!(:help).and_return('')
173
+ Fission::Command::Delete.should_receive(:new).
174
+ with(['foo', '--force']).
175
+ and_return(@cmd_mock)
176
+ Fission::CLI.execute ['delete', 'foo', '--force']
177
+ end
98
178
  end
99
179
  end
100
180