fission 0.2.0 → 0.3.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.
@@ -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