fission 0.1.0 → 0.2.0

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/CHANGELOG.md CHANGED
@@ -2,5 +2,12 @@
2
2
 
3
3
  ## head
4
4
 
5
+ ## 0.2.0 (07/13/2011)
6
+ * add 'status' command
7
+ * add 'start' command
8
+ * add 'stop' command
9
+ * add 'suspend' command
10
+ * add support for cloning single and split disk VMs
11
+
5
12
  ## 0.1.0 (05/17/2011)
6
13
  Initial release
data/README.md CHANGED
@@ -1,19 +1,7 @@
1
1
  # Fission
2
2
 
3
3
  ## Intro
4
- Fission is a simple command line tool for cloning of VMware Fusion VMs.
5
-
6
-
7
- ## Config
8
- By default, fission will use the default VMware Fusion VM directory
9
- (~/Documents/Virtual Machines.localized/) when cloning. If you want to use a
10
- different directory, you can set this in a config file.
11
-
12
- The config file needs to be in yaml format and live at '~/.fissionrc'
13
-
14
- $cat ~/.fissionrc
15
- ---
16
- vm_dir: "/vm"
4
+ Fission is a simple command line tool for managing VMware Fusion VMs.
17
5
 
18
6
 
19
7
  ## Install
@@ -22,7 +10,29 @@ The config file needs to be in yaml format and live at '~/.fissionrc'
22
10
 
23
11
  ## Usage
24
12
  ### Clone
25
- fission clone existing_vm new_vm
13
+ fission clone existing_vm new_vm [--start]
14
+
15
+ If you provide '--start', then the new VM will be powered on after cloning
16
+
17
+ ### Start
18
+ fission start my_vm
19
+
20
+ Starts the VM
21
+
22
+ ### Status
23
+ fission status
24
+
25
+ Displays the status (running or not) of all of the VMs found
26
+
27
+ ### Stop
28
+ fission stop my_vm
29
+
30
+ Stops the VM
31
+
32
+ ### Suspend
33
+ fission suspend my_vm
34
+
35
+ Suspends the VM
26
36
 
27
37
  ### Help
28
38
  fission -h
@@ -32,7 +42,23 @@ or just
32
42
  fission
33
43
 
34
44
 
45
+ ## Config
46
+ By default, fission will use the default VMware Fusion VM directory
47
+ (~/Documents/Virtual Machines.localized/) when cloning. If you want to use a
48
+ different directory, you can set this in a config file.
49
+
50
+ The config file needs to be in yaml format and live at '~/.fissionrc'
51
+
52
+ $cat ~/.fissionrc
53
+ ---
54
+ vm_dir: "/vm"
55
+
56
+
35
57
  ## Other Notable Info
58
+ The name of the VM used in the previous examples should be the directory name
59
+ of the VM minus the '.vmwarevm' extension. Typically the VM name and the
60
+ directory name are the same.
61
+
36
62
  As of now, VMware Fusion doesn't provide an easy, out of
37
63
  the box, way to modify the personality (hostname, ip, etc.) of a VM. Because of
38
64
  this, a clone created by fission is an _exact_ copy of the original (including
@@ -40,8 +66,8 @@ hostname, ip address, etc.). Most likely, this isn't what you want.
40
66
 
41
67
  One approach is to create a VM which will act as a template. Create the VM with
42
68
  the desired install method (ideally with easy install) and settings, but do not
43
- power on the VM. You can create clones from this VM and when you power it on,
44
- it will start the OS install process (and assign a new ip, etc.)
69
+ power on the VM. You can then create clones from this VM 'template'. When you
70
+ power on the clone, it will start the OS install process (and assign a new ip, etc.).
45
71
 
46
72
 
47
73
  ## Contribute
@@ -49,3 +75,7 @@ it will start the OS install process (and assign a new ip, etc.)
49
75
  * Make your feature addition or bug fix (with tests) in a topic branch
50
76
  * Bonus points for not mucking with the gemspec or version
51
77
  * Send a pull request and I'll get it integrated
78
+
79
+
80
+ ## License
81
+ See LICENSE
data/lib/fission.rb CHANGED
@@ -8,8 +8,13 @@ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
8
8
  require 'fission/cli'
9
9
  require 'fission/command'
10
10
  require 'fission/command/clone'
11
+ require 'fission/command/start'
12
+ require 'fission/command/status'
13
+ require 'fission/command/stop'
14
+ require 'fission/command/suspend'
11
15
  require 'fission/config'
12
16
  require 'fission/core_ext/class'
17
+ require 'fission/core_ext/file'
13
18
  require 'fission/core_ext/object'
14
19
  require 'fission/ui'
15
20
  require 'fission/vm'
data/lib/fission/cli.rb CHANGED
@@ -28,15 +28,22 @@ module Fission
28
28
  exit(1)
29
29
  end
30
30
 
31
- case args.first
32
- when 'clone'
33
- @command = Fission::Command::Clone.new args.drop 1
34
- @command.execute
31
+ if commands.include?(args.first)
32
+ @cmd = Fission::Command.const_get(args.first.capitalize).new args.drop 1
33
+ @cmd.execute
35
34
  else
36
35
  show_all_help(optparse)
37
- exit(0)
36
+ exit(1)
37
+ end
38
+ end
39
+
40
+ def self.commands
41
+ cmds = []
42
+ Dir.entries(File.join(File.dirname(__FILE__), 'command')).select do |file|
43
+ cmds << File.basename(file, '.rb') unless File.directory? file
38
44
  end
39
45
 
46
+ cmds
40
47
  end
41
48
 
42
49
  private
@@ -0,0 +1,42 @@
1
+ module Fission
2
+ class Command
3
+ class Start < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ end
8
+
9
+ def execute
10
+ unless args.count == 1
11
+ Fission.ui.output self.class.help
12
+ Fission.ui.output ""
13
+ Fission.ui.output_and_exit "Incorrect arguments for start command", 1
14
+ end
15
+
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
20
+ end
21
+
22
+ if VM.all_running.include?(vm_name)
23
+ Fission.ui.output ''
24
+ Fission.ui.output_and_exit "VM '#{vm_name}' is already running", 0
25
+ end
26
+
27
+ Fission.ui.output "Starting '#{vm_name}'"
28
+ @vm = Fission::VM.new vm_name
29
+ @vm.start
30
+ end
31
+
32
+ def option_parser
33
+ optparse = OptionParser.new do |opts|
34
+ opts.banner = "\nstart usage: fission start vm"
35
+ end
36
+
37
+ optparse
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ module Fission
2
+ class Command
3
+ class Status < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ end
8
+
9
+ def execute
10
+ all_vms = VM.all
11
+ all_running_vms = VM.all_running
12
+
13
+ longest_vm_name = all_vms.max { |a,b| a.length <=> b.length }
14
+
15
+ VM.all.each do |vm|
16
+ status = all_running_vms.include?(vm) ? '[running]' : '[not running]'
17
+ Fission.ui.output_printf "%-#{longest_vm_name.length}s %s\n", vm, status
18
+ end
19
+ end
20
+
21
+ def option_parser
22
+ optparse = OptionParser.new do |opts|
23
+ opts.banner = "\nstatus usage: fission status"
24
+ end
25
+
26
+ optparse
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ module Fission
2
+ class Command
3
+ class Stop < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ end
8
+
9
+ def execute
10
+ unless args.count == 1
11
+ Fission.ui.output self.class.help
12
+ Fission.ui.output ""
13
+ Fission.ui.output_and_exit "Incorrect arguments for stop command", 1
14
+ end
15
+
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
20
+ end
21
+
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
+ end
26
+
27
+ Fission.ui.output "Stopping '#{vm_name}'"
28
+ @vm = Fission::VM.new vm_name
29
+ @vm.stop
30
+ end
31
+
32
+ def option_parser
33
+ optparse = OptionParser.new do |opts|
34
+ opts.banner = "\nstop usage: fission stop vm"
35
+ end
36
+
37
+ optparse
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ module Fission
2
+ class Command
3
+ class Suspend < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ end
8
+
9
+ def execute
10
+ unless args.count == 1
11
+ Fission.ui.output self.class.help
12
+ Fission.ui.output ""
13
+ Fission.ui.output_and_exit "Incorrect arguments for suspend command", 1
14
+ end
15
+
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
20
+ end
21
+
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
+ end
26
+
27
+ Fission.ui.output "suspending '#{vm_name}'"
28
+ @vm = Fission::VM.new vm_name
29
+ @vm.suspend
30
+ end
31
+
32
+ def option_parser
33
+ optparse = OptionParser.new do |opts|
34
+ opts.banner = "\nsuspend usage: fission suspend vm"
35
+ end
36
+
37
+ optparse
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -13,6 +13,7 @@ module Fission
13
13
  end
14
14
 
15
15
  @attributes['vmrun_bin'] = '/Library/Application Support/VMware Fusion/vmrun'
16
+ @attributes['vmrun_cmd'] = "#{@attributes['vmrun_bin'].gsub(' ', '\ ')} -T fusion"
16
17
  end
17
18
 
18
19
  private
@@ -0,0 +1,7 @@
1
+ class File
2
+ # from ptools
3
+ def self.binary?(file)
4
+ s = (File.read(file, File.stat(file).blksize) || "").split(//)
5
+ ((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
6
+ end
7
+ end
data/lib/fission/ui.rb CHANGED
@@ -10,6 +10,10 @@ module Fission
10
10
  @stdout.puts s
11
11
  end
12
12
 
13
+ def output_printf(string, key, value)
14
+ @stdout.send :printf, string, key, value
15
+ end
16
+
13
17
  def output_and_exit(s, exit_code)
14
18
  output s
15
19
  exit exit_code
@@ -1,3 +1,3 @@
1
1
  module Fission
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/fission/vm.rb CHANGED
@@ -7,7 +7,7 @@ module Fission
7
7
  end
8
8
 
9
9
  def start
10
- command = "#{Fission.config.attributes['vmrun_bin'].gsub(' ', '\ ' )} -T fusion start #{conf_file.gsub ' ', '\ '} gui 2>&1"
10
+ command = "#{Fission.config.attributes['vmrun_cmd']} start #{conf_file.gsub ' ', '\ '} gui 2>&1"
11
11
  output = `#{command}`
12
12
 
13
13
  if $?.exitstatus == 0
@@ -17,10 +17,62 @@ module Fission
17
17
  end
18
18
  end
19
19
 
20
+ def stop
21
+ command = "#{Fission.config.attributes['vmrun_cmd']} stop #{conf_file.gsub ' ', '\ '} 2>&1"
22
+ output = `#{command}`
23
+
24
+ if $?.exitstatus == 0
25
+ Fission.ui.output "VM stopped"
26
+ else
27
+ Fission.ui.output "There was a problem stopping the VM. The error was:\n#{output}"
28
+ end
29
+ end
30
+
31
+ def suspend
32
+ command = "#{Fission.config.attributes['vmrun_cmd']} suspend #{conf_file.gsub ' ', '\ '} 2>&1"
33
+ output = `#{command}`
34
+
35
+ if $?.exitstatus == 0
36
+ Fission.ui.output "VM suspended"
37
+ else
38
+ Fission.ui.output "There was a problem suspending the VM. The error was:\n#{output}"
39
+ end
40
+ end
41
+
20
42
  def conf_file
21
43
  File.join self.class.path(@name), "#{@name}.vmx"
22
44
  end
23
45
 
46
+ def self.all
47
+ vm_dirs = Dir[File.join Fission.config.attributes['vm_dir'], '*.vmwarevm'].select do |d|
48
+ File.directory? d
49
+ end
50
+
51
+ vm_dirs.map { |d| File.basename d, '.vmwarevm' }
52
+ end
53
+
54
+ def self.all_running
55
+ command = "#{Fission.config.attributes['vmrun_cmd']} list"
56
+
57
+ output = `#{command}`
58
+
59
+ vms = []
60
+
61
+ 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
68
+ end
69
+ else
70
+ Fission.ui.output_and_exit "Unable to determine the list of running VMs", 1
71
+ end
72
+
73
+ vms
74
+ end
75
+
24
76
  def self.exists?(vm_name)
25
77
  File.directory? path(vm_name)
26
78
  end
@@ -50,11 +102,13 @@ module Fission
50
102
  end
51
103
 
52
104
  def self.update_config(from, to)
53
- ['.vmdk', '.vmx', '.vmxf'].each do |ext|
105
+ ['.vmx', '.vmxf', '.vmdk'].each do |ext|
54
106
  file = File.join path(to), "#{to}#{ext}"
55
- text = File.read file
56
- text.gsub! from, to
57
- File.open(file, 'w'){ |f| f.print text }
107
+
108
+ unless File.binary?(file)
109
+ text = (File.read file).gsub from, to
110
+ File.open(file, 'w'){ |f| f.print text }
111
+ end
58
112
  end
59
113
  end
60
114
 
@@ -6,6 +6,12 @@ describe Fission::CLI do
6
6
  Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
7
7
  end
8
8
 
9
+ describe 'self.commands' do
10
+ it 'should return the list of commands' do
11
+ Fission::CLI.commands.should == ['clone', 'start', 'status', 'stop', 'suspend']
12
+ end
13
+ end
14
+
9
15
  describe 'execute' do
10
16
 
11
17
  describe 'with no arguments' do
@@ -45,17 +51,50 @@ describe Fission::CLI do
45
51
 
46
52
  end
47
53
 
48
- describe 'clone' do
54
+ describe 'with the sub command' do
49
55
  before :each do
50
- @clone_mock = mock('clone_mock')
51
- Fission::Command::Clone.stub!(:help).and_return('')
56
+ @cmd_mock = mock('cmd')
57
+ @cmd_mock.should_receive(:execute)
58
+ end
59
+
60
+ describe 'clone' do
61
+ it "should try to clone the vm" do
62
+ Fission::Command::Clone.stub!(:help).and_return('')
63
+ Fission::Command::Clone.should_receive(:new).with(['foo', 'bar']).and_return(@cmd_mock)
64
+ Fission::CLI.execute ['clone', 'foo', 'bar']
65
+ end
52
66
  end
53
67
 
54
- it "should try to clone the vm" do
55
- @clone_mock.should_receive(:execute)
56
- Fission::Command::Clone.should_receive(:new).with(['foo', 'bar']).and_return(@clone_mock)
68
+ describe 'start' do
69
+ it "should try to start the vm" do
70
+ Fission::Command::Start.stub!(:help).and_return('')
71
+ Fission::Command::Start.should_receive(:new).with(['foo']).and_return(@cmd_mock)
72
+ Fission::CLI.execute ['start', 'foo']
73
+ end
74
+ end
57
75
 
58
- Fission::CLI.execute ['clone', 'foo', 'bar']
76
+ describe 'status' do
77
+ it "should try to get the status for all VMs" do
78
+ Fission::Command::Status.stub!(:help).and_return('')
79
+ Fission::Command::Status.should_receive(:new).and_return(@cmd_mock)
80
+ Fission::CLI.execute ['status']
81
+ end
82
+ end
83
+
84
+ describe 'stop' do
85
+ it "should try to stop the vm" do
86
+ Fission::Command::Stop.stub!(:help).and_return('')
87
+ Fission::Command::Stop.should_receive(:new).with(['foo']).and_return(@cmd_mock)
88
+ Fission::CLI.execute ['stop', 'foo']
89
+ end
90
+ end
91
+
92
+ describe 'suspend' do
93
+ it "should try to suspend the vm" do
94
+ Fission::Command::Suspend.stub!(:help).and_return('')
95
+ Fission::Command::Suspend.should_receive(:new).with(['foo']).and_return(@cmd_mock)
96
+ Fission::CLI.execute ['suspend', 'foo']
97
+ end
59
98
  end
60
99
  end
61
100
 
@@ -0,0 +1,71 @@
1
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Command::Start do
4
+ before :all do
5
+ @vm_info = ['foo']
6
+ end
7
+
8
+ before :each do
9
+ @string_io = StringIO.new
10
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
11
+ end
12
+
13
+ describe 'execute' do
14
+ it "should output an error and the help when no VM argument is passed in" do
15
+ Fission::Command::Start.should_receive(:help)
16
+
17
+ lambda {
18
+ command = Fission::Command::Start.new
19
+ command.execute
20
+ }.should raise_error SystemExit
21
+
22
+ @string_io.string.should match /Incorrect arguments for start command/
23
+ end
24
+
25
+ it "should output an error and exit if it can't find the vm" do
26
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(false)
27
+
28
+ lambda {
29
+ command = Fission::Command::Start.new @vm_info
30
+ command.execute
31
+ }.should raise_error SystemExit
32
+
33
+ @string_io.string.should match /Unable to find the VM #{@vm_info.first}/
34
+ end
35
+
36
+
37
+ it "should output and exit if the vm is already running" do
38
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
39
+ Fission::VM.should_receive(:all_running).and_return(@vm_info)
40
+
41
+ lambda {
42
+ command = Fission::Command::Start.new @vm_info
43
+ command.execute
44
+ }.should raise_error SystemExit
45
+
46
+ @string_io.string.should match /VM '#{@vm_info.first}' is already running/
47
+ end
48
+
49
+ it 'should try to start the vm if it is not running' do
50
+ @vm_mock = mock('vm_mock')
51
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
52
+ Fission::VM.should_receive(:all_running).and_return([])
53
+ Fission::VM.should_receive(:new).with(@vm_info.first).and_return(@vm_mock)
54
+ @vm_mock.should_receive(:start)
55
+
56
+ command = Fission::Command::Start.new @vm_info
57
+ command.execute
58
+
59
+ @string_io.string.should match /Starting '#{@vm_info.first}'/
60
+ end
61
+
62
+ end
63
+
64
+ describe 'help' do
65
+ it 'should output info for this command' do
66
+ output = Fission::Command::Start.help
67
+
68
+ output.should match /start vm/
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Command::Status do
4
+ before :each do
5
+ @string_io = StringIO.new
6
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
7
+ end
8
+
9
+ describe 'execute' do
10
+ before :each do
11
+ Fission::VM.stub!(:all).and_return(['foo', 'bar', 'baz'])
12
+ Fission::VM.stub!(:all_running).and_return(['foo', 'baz'])
13
+ end
14
+
15
+ it 'should output the VMs which are running' do
16
+ command = Fission::Command::Status.new
17
+ command.execute
18
+
19
+ @string_io.string.should match /foo.+[running]/
20
+ @string_io.string.should match /baz.+[running]/
21
+ end
22
+
23
+ it 'should output the VMs which are not running' do
24
+ command = Fission::Command::Status.new
25
+ command.execute
26
+
27
+ @string_io.string.should match /bar.+[not running]/
28
+ end
29
+ end
30
+
31
+ describe 'help' do
32
+ it 'should output info for this command' do
33
+ output = Fission::Command::Status.help
34
+
35
+ output.should match /status/
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Command::Stop do
4
+ before :all do
5
+ @vm_info = ['foo']
6
+ end
7
+
8
+ before :each do
9
+ @string_io = StringIO.new
10
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
11
+ end
12
+
13
+ describe 'execute' do
14
+ it "should output an error and the help when no VM argument is passed in" do
15
+ Fission::Command::Stop.should_receive(:help)
16
+
17
+ lambda {
18
+ command = Fission::Command::Stop.new
19
+ command.execute
20
+ }.should raise_error SystemExit
21
+
22
+ @string_io.string.should match /Incorrect arguments for stop command/
23
+ end
24
+
25
+ it "should output an error and exit if it can't find the vm" do
26
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(false)
27
+
28
+ lambda {
29
+ command = Fission::Command::Stop.new @vm_info
30
+ command.execute
31
+ }.should raise_error SystemExit
32
+
33
+ @string_io.string.should match /Unable to find the VM #{@vm_info.first}/
34
+ end
35
+
36
+
37
+ it "should output and exit if the vm is not running" do
38
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
39
+ Fission::VM.should_receive(:all_running).and_return([])
40
+
41
+ lambda {
42
+ command = Fission::Command::Stop.new @vm_info
43
+ command.execute
44
+ }.should raise_error SystemExit
45
+
46
+ @string_io.string.should match /VM '#{@vm_info.first}' is not running/
47
+ end
48
+
49
+ it 'should try to stop the vm if it is not running' do
50
+ @vm_mock = mock('vm_mock')
51
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
52
+ Fission::VM.should_receive(:all_running).and_return(@vm_info)
53
+ Fission::VM.should_receive(:new).with(@vm_info.first).and_return(@vm_mock)
54
+ @vm_mock.should_receive(:stop)
55
+
56
+ command = Fission::Command::Stop.new @vm_info
57
+ command.execute
58
+
59
+ @string_io.string.should match /Stopping '#{@vm_info.first}'/
60
+ end
61
+
62
+ end
63
+
64
+ describe 'help' do
65
+ it 'should output info for this command' do
66
+ output = Fission::Command::Stop.help
67
+
68
+ output.should match /stop vm/
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path('../../../spec_helper.rb', __FILE__)
2
+
3
+ describe Fission::Command::Suspend do
4
+ before :all do
5
+ @vm_info = ['foo']
6
+ end
7
+
8
+ before :each do
9
+ @string_io = StringIO.new
10
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
11
+ end
12
+
13
+ describe 'execute' do
14
+ it "should output an error and the help when no VM argument is passed in" do
15
+ Fission::Command::Suspend.should_receive(:help)
16
+
17
+ lambda {
18
+ command = Fission::Command::Suspend.new
19
+ command.execute
20
+ }.should raise_error SystemExit
21
+
22
+ @string_io.string.should match /Incorrect arguments for suspend command/
23
+ end
24
+
25
+ it "should output an error and exit if it can't find the vm" do
26
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(false)
27
+
28
+ lambda {
29
+ command = Fission::Command::Suspend.new @vm_info
30
+ command.execute
31
+ }.should raise_error SystemExit
32
+
33
+ @string_io.string.should match /Unable to find the VM #{@vm_info.first}/
34
+ end
35
+
36
+
37
+ it "should output and exit if the vm is not running" do
38
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
39
+ Fission::VM.should_receive(:all_running).and_return([])
40
+
41
+ lambda {
42
+ command = Fission::Command::Suspend.new @vm_info
43
+ command.execute
44
+ }.should raise_error SystemExit
45
+
46
+ @string_io.string.should match /VM '#{@vm_info.first}' is not running/
47
+ end
48
+
49
+ it 'should try to suspend the vm if it is running' do
50
+ @vm_mock = mock('vm_mock')
51
+ Fission::VM.should_receive(:exists?).with(@vm_info.first).and_return(true)
52
+ Fission::VM.should_receive(:all_running).and_return([@vm_info.first])
53
+ Fission::VM.should_receive(:new).with(@vm_info.first).and_return(@vm_mock)
54
+ @vm_mock.should_receive(:suspend)
55
+
56
+ command = Fission::Command::Suspend.new @vm_info
57
+ command.execute
58
+
59
+ @string_io.string.should match /suspending '#{@vm_info.first}'/
60
+ end
61
+
62
+ end
63
+
64
+ describe 'help' do
65
+ it 'should output info for this command' do
66
+ output = Fission::Command::Suspend.help
67
+
68
+ output.should match /suspend vm/
69
+ end
70
+ end
71
+ end
@@ -25,6 +25,13 @@ describe Fission::Config do
25
25
  end
26
26
  end
27
27
 
28
+ it 'should set vmrun_cmd' do
29
+ FakeFS do
30
+ @config = Fission::Config.new
31
+ @config.attributes['vmrun_cmd'].should == '/Library/Application\ Support/VMware\ Fusion/vmrun -T fusion'
32
+ end
33
+ end
34
+
28
35
  end
29
36
 
30
37
  end
@@ -11,6 +11,14 @@ describe Fission::UI do
11
11
  end
12
12
  end
13
13
 
14
+ describe 'output_printf' do
15
+ it 'should pass the arguments to printf' do
16
+ @output = mock('output')
17
+ @output.should_receive(:printf).with('foo', 'bar', 'baz')
18
+ Fission::UI.new(@output).output_printf('foo', 'bar', 'baz')
19
+ end
20
+ end
21
+
14
22
  describe 'output_and_exit' do
15
23
  it 'should show the desired text and exit with the desired exit code' do
16
24
  Fission::UI.any_instance.should_receive(:exit).and_return(1)
@@ -13,9 +13,12 @@ describe Fission::VM do
13
13
 
14
14
  describe 'start' do
15
15
  it 'should output that it was successful' do
16
+ $?.should_receive(:exitstatus).and_return(0)
16
17
  Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
17
18
  @vm = Fission::VM.new('foo')
18
- @vm.should_receive(:`).with("#{Fission.config.attributes['vmrun_bin'].gsub ' ', '\ '} -T fusion start #{(File.join(Fission::VM.path('foo'), 'foo.vmx')).gsub ' ', '\ '} gui 2>&1").and_return("it's all good")
19
+ @vm.should_receive(:`).
20
+ with("#{Fission.config.attributes['vmrun_cmd']} start #{@vm.conf_file.gsub(' ', '\ ')} gui 2>&1").
21
+ and_return("it's all good")
19
22
  @vm.start
20
23
 
21
24
  @string_io.string.should match /VM started/
@@ -25,19 +28,126 @@ describe Fission::VM do
25
28
  $?.should_receive(:exitstatus).and_return(1)
26
29
  Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
27
30
  @vm = Fission::VM.new('foo')
28
- @vm.should_receive(:`).with("#{Fission.config.attributes['vmrun_bin'].gsub ' ', '\ '} -T fusion start #{(File.join(Fission::VM.path('foo'), 'foo.vmx')).gsub ' ', '\ '} gui 2>&1").and_return("it blew up")
31
+ @vm.should_receive(:`).
32
+ with("#{Fission.config.attributes['vmrun_cmd']} start #{@vm.conf_file.gsub(' ', '\ ')} gui 2>&1").
33
+ and_return("it blew up")
29
34
  @vm.start
30
35
 
31
36
  @string_io.string.should match /There was a problem starting the VM.+it blew up.+/m
32
37
  end
33
38
  end
34
39
 
40
+ describe 'stop' do
41
+ it 'should output that it was successful' do
42
+ $?.should_receive(:exitstatus).and_return(0)
43
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
44
+ @vm = Fission::VM.new('foo')
45
+ @vm.should_receive(:`).
46
+ with("#{Fission.config.attributes['vmrun_cmd']} stop #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
47
+ and_return("it's all good")
48
+ @vm.stop
49
+
50
+ @string_io.string.should match /VM stopped/
51
+ end
52
+
53
+ it 'it should output that it was unsuccessful' do
54
+ $?.should_receive(:exitstatus).and_return(1)
55
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
56
+ @vm = Fission::VM.new('foo')
57
+ @vm.should_receive(:`).
58
+ with("#{Fission.config.attributes['vmrun_cmd']} stop #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
59
+ and_return("it blew up")
60
+ @vm.stop
61
+
62
+ @string_io.string.should match /There was a problem stopping the VM.+it blew up.+/m
63
+ end
64
+ end
65
+
66
+ describe 'suspend' do
67
+ it 'should output that it was successful' do
68
+ $?.should_receive(:exitstatus).and_return(0)
69
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
70
+ @vm = Fission::VM.new('foo')
71
+ @vm.should_receive(:`).
72
+ with("#{Fission.config.attributes['vmrun_cmd']} suspend #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
73
+ and_return("it's all good")
74
+ @vm.suspend
75
+
76
+ @string_io.string.should match /VM suspended/
77
+ end
78
+
79
+ it 'it should output that it was unsuccessful' do
80
+ $?.should_receive(:exitstatus).and_return(1)
81
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
82
+ @vm = Fission::VM.new('foo')
83
+ @vm.should_receive(:`).
84
+ with("#{Fission.config.attributes['vmrun_cmd']} suspend #{@vm.conf_file.gsub ' ', '\ '} 2>&1").
85
+ and_return("it blew up")
86
+ @vm.suspend
87
+
88
+ @string_io.string.should match /There was a problem suspending the VM.+it blew up.+/m
89
+ end
90
+ end
91
+
35
92
  describe 'conf_file' do
36
93
  it 'should return the path to the conf file' do
37
94
  Fission::VM.new('foo').conf_file.should == File.join(Fission.config.attributes['vm_dir'], 'foo.vmwarevm', 'foo.vmx')
38
95
  end
39
96
  end
40
97
 
98
+ describe "self.all" do
99
+ it "should return the list of VMs" do
100
+ vm_root = Fission.config.attributes['vm_dir']
101
+ Dir.should_receive(:[]).and_return(["#{File.join vm_root, 'foo.vmwarevm' }", "#{File.join vm_root, 'bar.vmwarevm' }"])
102
+
103
+ vm_root = Fission.config.attributes['vm_dir']
104
+ File.should_receive(:directory?).with("#{File.join vm_root, 'foo.vmwarevm'}").and_return(true)
105
+ File.should_receive(:directory?).with("#{File.join vm_root, 'bar.vmwarevm'}").and_return(true)
106
+ Fission::VM.all.should == ['foo', 'bar']
107
+ end
108
+
109
+ it "should not return an item in the list if it isn't a directory" do
110
+ vm_root = Fission.config.attributes['vm_dir']
111
+ Dir.should_receive(:[]).and_return((['foo', 'bar', 'baz'].map { |i| File.join vm_root, "#{i}.vmwarevm"}))
112
+ File.should_receive(:directory?).with("#{File.join vm_root, 'foo.vmwarevm'}").and_return(true)
113
+ File.should_receive(:directory?).with("#{File.join vm_root, 'bar.vmwarevm'}").and_return(true)
114
+ File.should_receive(:directory?).with("#{File.join vm_root, 'baz.vmwarevm'}").and_return(false)
115
+ Fission::VM.all.should == ['foo', 'bar']
116
+ end
117
+
118
+ it "should only query for items with an extension of .vmwarevm" do
119
+ dir_arg = File.join Fission.config.attributes['vm_dir'], '*.vmwarevm'
120
+ Dir.should_receive(:[]).with(dir_arg).and_return(['foo.vmwarevm', 'bar.vmwarevm'])
121
+ Fission::VM.all
122
+ end
123
+ end
124
+
125
+ describe 'self.all_running' do
126
+ it 'should list the running vms' do
127
+ list_output = "Total running VMs: 2\n/vm/foo.vmwarevm/foo.vmx\n/vm/bar.vmwarevm/bar.vmx\n/vm/baz.vmwarevm/baz.vmx\n"
128
+
129
+ $?.should_receive(:exitstatus).and_return(0)
130
+ Fission::VM.should_receive(:`).with("#{Fission.config.attributes['vmrun_cmd']} list").and_return(list_output)
131
+ [ 'foo', 'bar', 'baz'].each do |vm|
132
+ File.should_receive(:exists?).with("/vm/#{vm}.vmwarevm/#{vm}.vmx").and_return(true)
133
+ end
134
+
135
+ Fission::VM.all_running.should == ['foo', 'bar', 'baz']
136
+ end
137
+
138
+ it 'should output an error and exit if unable to get the list of running vms' do
139
+ $?.should_receive(:exitstatus).and_return(1)
140
+ Fission::VM.should_receive(:`).with("#{Fission.config.attributes['vmrun_cmd']} list").and_return("it blew up")
141
+ Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
142
+
143
+ lambda {
144
+ Fission::VM.all_running
145
+ }.should raise_error SystemExit
146
+
147
+ @string_io.string.should match /Unable to determine the list of running VMs/
148
+ end
149
+ end
150
+
41
151
  describe "self.path" do
42
152
  it "should return the path of the vm" do
43
153
  vm_path = File.join(Fission.config.attributes['vm_dir'], 'foo.vmwarevm').gsub '\\', ''
@@ -61,45 +171,75 @@ describe Fission::VM do
61
171
  end
62
172
  end
63
173
 
64
-
65
174
  describe "self.clone" do
66
175
  before :each do
67
176
  Fission.stub!(:ui).and_return(Fission::UI.new(@string_io))
68
- end
177
+ @source_vm = 'foo'
178
+ @target_vm = 'bar'
179
+ @vm_files = ['.vmx', '.vmxf', '.vmdk', '-s001.vmdk', '-s002.vmdk', '.vmsd']
69
180
 
70
- it 'should clone the vm to the target' do
71
- source_vm = 'foo'
72
- target_vm = 'bar'
73
- vm_files = [ '.vmx',
74
- '.vmxf',
75
- '.vmdk',
76
- '-s001.vmdk',
77
- '-s002.vmdk',
78
- '.vmsd' ]
181
+ FakeFS.activate!
79
182
 
80
- FakeFS do
81
- FileUtils.mkdir_p Fission::VM.path('foo')
183
+ FileUtils.mkdir_p Fission::VM.path('foo')
184
+
185
+ @vm_files.each do |file|
186
+ FileUtils.touch File.join(Fission::VM.path('foo'), "#{@source_vm}#{file}")
187
+ end
82
188
 
83
- vm_files.each do |file|
84
- FileUtils.touch File.join(Fission::VM.path('foo'), "#{source_vm}#{file}")
85
- end
189
+ ['.vmx', '.vmxf', '.vmdk'].each do |ext|
190
+ File.open(File.join(Fission::VM.path('foo'), "foo#{ext}"), 'w') { |f| f.write 'foo.vmdk'}
191
+ end
86
192
 
87
- File.open(File.join(Fission::VM.path('foo'), 'foo.vmx'), 'w') { |f| f.write 'foo.vmdk'}
193
+ ['.vmx', '.vmxf'].each do |ext|
194
+ File.should_receive(:binary?).with(File.join(Fission::VM.path('bar'), "bar#{ext}")).and_return(false)
195
+ end
196
+ end
88
197
 
89
- Fission::VM.clone source_vm, target_vm
198
+ after :each do
199
+ FakeFS.deactivate!
200
+ end
90
201
 
91
- File.directory?(Fission::VM.path('bar')).should == true
202
+ it 'should copy the vm files to the target' do
203
+ File.should_receive(:binary?).with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(true)
204
+ Fission::VM.clone @source_vm, @target_vm
205
+
206
+ File.directory?(Fission::VM.path('bar')).should == true
207
+
208
+ @vm_files.each do |file|
209
+ File.file?(File.join(Fission::VM.path('bar'), "#{@target_vm}#{file}")).should == true
210
+ end
211
+ end
92
212
 
93
- vm_files.each do |file|
94
- File.file?(File.join(Fission::VM.path('bar'), "#{target_vm}#{file}")).should == true
95
- end
213
+ it 'should update the target vm config files' do
214
+ File.should_receive(:binary?).with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(true)
215
+ Fission::VM.clone @source_vm, @target_vm
96
216
 
97
- conf_file = File.read File.join(Fission::VM.path('bar'), 'bar.vmx')
98
- conf_file.should == 'bar.vmdk'
217
+ ['.vmx', '.vmxf'].each do |ext|
218
+ File.read(File.join(Fission::VM.path('bar'), "bar#{ext}")).should_not match /foo/
219
+ File.read(File.join(Fission::VM.path('bar'), "bar#{ext}")).should match /bar/
99
220
  end
221
+ end
222
+
223
+ it "should not try to update the vmdk file if it's not a sparse disk" do
224
+ File.should_receive(:binary?).with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(true)
225
+ Fission::VM.clone @source_vm, @target_vm
226
+
227
+ File.read(File.join(Fission::VM.path('bar'), 'bar.vmdk')).should match /foo/
228
+ end
229
+
230
+ it "should update the vmdk when a sparse disk is found" do
231
+ File.should_receive(:binary?).with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(false)
232
+ Fission::VM.clone @source_vm, @target_vm
233
+
234
+ File.read(File.join(Fission::VM.path('bar'), 'bar.vmdk')).should match /bar/
235
+ end
236
+
237
+ it 'should output that the clone was successful' do
238
+ File.should_receive(:binary?).with(File.join(Fission::VM.path('bar'), "bar.vmdk")).and_return(true)
239
+ Fission::VM.clone @source_vm, @target_vm
100
240
 
101
- @string_io.string.should match /Cloning #{source_vm} to #{target_vm}/
102
- @string_io.string.should match /Configuring #{target_vm}/
241
+ @string_io.string.should match /Cloning #{@source_vm} to #{@target_vm}/
242
+ @string_io.string.should match /Configuring #{@target_vm}/
103
243
  end
104
244
 
105
245
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: fission
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.2.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Tommy Bishop
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-05-18 00:00:00 Z
13
+ date: 2011-07-14 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -58,14 +58,23 @@ files:
58
58
  - lib/fission/cli.rb
59
59
  - lib/fission/command.rb
60
60
  - lib/fission/command/clone.rb
61
+ - lib/fission/command/start.rb
62
+ - lib/fission/command/status.rb
63
+ - lib/fission/command/stop.rb
64
+ - lib/fission/command/suspend.rb
61
65
  - lib/fission/config.rb
62
66
  - lib/fission/core_ext/class.rb
67
+ - lib/fission/core_ext/file.rb
63
68
  - lib/fission/core_ext/object.rb
64
69
  - lib/fission/ui.rb
65
70
  - lib/fission/version.rb
66
71
  - lib/fission/vm.rb
67
72
  - spec/fission/cli_spec.rb
68
73
  - spec/fission/command/clone_spec.rb
74
+ - spec/fission/command/start_spec.rb
75
+ - spec/fission/command/status_spec.rb
76
+ - spec/fission/command/stop_spec.rb
77
+ - spec/fission/command/suspend_spec.rb
69
78
  - spec/fission/command_spec.rb
70
79
  - spec/fission/config_spec.rb
71
80
  - spec/fission/ui_spec.rb
@@ -95,13 +104,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
104
  requirements: []
96
105
 
97
106
  rubyforge_project: fission
98
- rubygems_version: 1.8.2
107
+ rubygems_version: 1.8.5
99
108
  signing_key:
100
109
  specification_version: 3
101
110
  summary: Tool to clone VMware fusion VMs
102
111
  test_files:
103
112
  - spec/fission/cli_spec.rb
104
113
  - spec/fission/command/clone_spec.rb
114
+ - spec/fission/command/start_spec.rb
115
+ - spec/fission/command/status_spec.rb
116
+ - spec/fission/command/stop_spec.rb
117
+ - spec/fission/command/suspend_spec.rb
105
118
  - spec/fission/command_spec.rb
106
119
  - spec/fission/config_spec.rb
107
120
  - spec/fission/ui_spec.rb