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.
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## head
4
4
 
5
+ ## 0.3.0 (09/08/2011)
6
+ * add ability to suspend all running VMs ('--all')
7
+ * add 'delete' command
8
+ * add 'snapshot create' command
9
+ * add 'snapshot list' command
10
+ * add 'snapshot revert' command
11
+ * add '--headless' option to start
12
+ * fix issue #2
13
+
5
14
  ## 0.2.0 (07/13/2011)
6
15
  * add 'status' command
7
16
  * add 'start' command
data/README.md CHANGED
@@ -14,11 +14,36 @@ Fission is a simple command line tool for managing VMware Fusion VMs.
14
14
 
15
15
  If you provide '--start', then the new VM will be powered on after cloning
16
16
 
17
+ ### Snapshot Create
18
+ fission snapshot create my_vm snapshot_name
19
+
20
+ Creates a snapshot for the VM
21
+
22
+ In order to create the snapshot:
23
+ * The VM must be running
24
+ * The snapshot name must be unique
25
+
26
+ ### Snapshot List
27
+ fission snapshot list my_vm
28
+
29
+ Lists the snapshots for the VM
30
+
31
+ ### Snapshot Revert
32
+ fission snapshot revert my_vm existing_snapshot
33
+
34
+ Reverts a VM to an existing snapshot
35
+
36
+ In order to revert to the snapshot:
37
+ * The Fusion GUI cannot be running
38
+
17
39
  ### Start
18
- fission start my_vm
40
+ fission start my_vm [--headless]
19
41
 
20
42
  Starts the VM
21
43
 
44
+ Providng '--headless' will start the VM without a Fusion GUI console
45
+ Note that the Fusion GUI cannot be running to start a VM with '--headless'
46
+
22
47
  ### Status
23
48
  fission status
24
49
 
@@ -30,9 +55,22 @@ Displays the status (running or not) of all of the VMs found
30
55
  Stops the VM
31
56
 
32
57
  ### Suspend
33
- fission suspend my_vm
58
+ fission suspend [my_vm | --all]
59
+
60
+ Suspends the VM or all running VMs
61
+
62
+ ### Delete
63
+ fission delete my_vm [--force]
64
+
65
+ Deletes the VM. This will delete the files from disk and remove the related metadata in Fusion.
66
+
67
+ By default, the VM will not be deleted if:
68
+ * The VM is running
69
+ * The Fusion GUI is running (as the metadata cannot be cleanly removed)
34
70
 
35
- Suspends the VM
71
+ Providing '--force' will:
72
+ * Stop the VM if it's running
73
+ * Delete the VM even if the Fusion GUI is running
36
74
 
37
75
  ### Help
38
76
  fission -h
@@ -69,6 +107,9 @@ the desired install method (ideally with easy install) and settings, but do not
69
107
  power on the VM. You can then create clones from this VM 'template'. When you
70
108
  power on the clone, it will start the OS install process (and assign a new ip, etc.).
71
109
 
110
+ ## Fission with RVM
111
+ Please see the following gist for a walkthrough of making fission available
112
+ regardless of ruby environment when using RVM https://gist.github.com/1203167
72
113
 
73
114
  ## Contribute
74
115
  * Fork the project
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
9
9
  s.authors = ['Tommy Bishop']
10
10
  s.email = ['bishop.thomas@gmail.com']
11
11
  s.homepage = "https://github.com/thbishop/fission"
12
- s.summary = %q{Tool to clone VMware fusion VMs}
13
- s.description = %q{A simple utility to create VMware Fusion VM clones}
12
+ s.summary = %q{Command line tool to manage VMware Fusion VMs}
13
+ s.description = %q{A simple utility to manage VMware Fusion VMs from the command line}
14
14
 
15
15
  s.rubyforge_project = "fission"
16
16
 
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
+ s.add_dependency 'CFPropertyList', '~> 2.0.17'
21
22
  s.add_development_dependency 'rspec', '~> 2.6.0'
22
23
  s.add_development_dependency 'fakefs', '~> 0.3.2'
23
24
  end
@@ -8,14 +8,20 @@ $:.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/snapshot_create'
12
+ require 'fission/command/snapshot_list'
13
+ require 'fission/command/snapshot_revert'
11
14
  require 'fission/command/start'
12
15
  require 'fission/command/status'
13
16
  require 'fission/command/stop'
14
17
  require 'fission/command/suspend'
18
+ require 'fission/command/delete'
15
19
  require 'fission/config'
16
20
  require 'fission/core_ext/class'
17
21
  require 'fission/core_ext/file'
18
22
  require 'fission/core_ext/object'
23
+ require 'fission/fusion'
24
+ require 'fission/metadata'
19
25
  require 'fission/ui'
20
26
  require 'fission/vm'
21
27
  require 'fission/version'
@@ -30,28 +30,34 @@ module Fission
30
30
 
31
31
  if commands.include?(args.first)
32
32
  @cmd = Fission::Command.const_get(args.first.capitalize).new args.drop 1
33
- @cmd.execute
33
+ elsif is_snapshot_command?(args)
34
+ klass = args.take(2).map {|c| c.capitalize}.join('')
35
+ @cmd = Fission::Command.const_get(klass).new args.drop 2
34
36
  else
35
37
  show_all_help(optparse)
36
38
  exit(1)
37
39
  end
40
+
41
+ @cmd.execute
38
42
  end
39
43
 
40
44
  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
45
+ cmds = Dir.entries(File.join(File.dirname(__FILE__), 'command')).select do |file|
46
+ !File.directory? file
44
47
  end
45
48
 
46
- cmds
49
+ cmds.map { |cmd| File.basename(cmd, '.rb').gsub '_', ' ' }
47
50
  end
48
51
 
49
52
  private
53
+ def self.is_snapshot_command?(args)
54
+ args.first == 'snapshot' && args.count > 1 && commands.include?(args.take(2).join(' '))
55
+ end
56
+
50
57
  def self.commands_banner
51
58
  text = "\nCommands:\n"
52
59
  Fission::Command.descendants.each do |command_klass|
53
60
  text << (command_klass.send :help)
54
- text << "\n\n"
55
61
  end
56
62
 
57
63
  text
@@ -8,7 +8,9 @@ module Fission
8
8
  end
9
9
 
10
10
  def execute
11
- unless args.count > 1
11
+ option_parser.parse! @args
12
+
13
+ unless @args.count > 1
12
14
  Fission.ui.output self.class.help
13
15
  Fission.ui.output ""
14
16
  Fission.ui.output_and_exit "Incorrect arguments for clone command", 1
@@ -25,9 +27,6 @@ module Fission
25
27
  Fission::ui.output_and_exit "The target vm #{target_vm} already exists", 1
26
28
  end
27
29
 
28
- clone_options = option_parser
29
- clone_options.parse! @args
30
-
31
30
  Fission::VM.clone source_vm, target_vm
32
31
 
33
32
  Fission.ui.output ''
@@ -0,0 +1,65 @@
1
+ module Fission
2
+ class Command
3
+ class Delete < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ @options.force = false
8
+ end
9
+
10
+ def execute
11
+ option_parser.parse! @args
12
+
13
+ if @args.count < 1
14
+ Fission.ui.output self.class.help
15
+ Fission.ui.output ""
16
+ Fission.ui.output_and_exit "Incorrect arguments for delete command", 1
17
+ end
18
+
19
+ target_vm = @args.first
20
+
21
+ unless Fission::VM.exists? target_vm
22
+ Fission.ui.output_and_exit "Unable to find target vm #{target_vm} (#{Fission::VM.path(target_vm)})", 1
23
+ end
24
+
25
+ if Fission::VM.all_running.include? target_vm
26
+ Fission.ui.output 'VM is currently running'
27
+ if @options.force
28
+ Fission.ui.output 'Going to stop it'
29
+ Fission::Command::Stop.new([target_vm]).execute
30
+ else
31
+ Fission.ui.output_and_exit "Either stop/suspend the VM or use '--force' and try again.", 1
32
+ end
33
+ end
34
+
35
+ if Fission::Fusion.is_running?
36
+ Fission.ui.output 'It looks like the Fusion GUI is currently running'
37
+ if @options.force
38
+ Fission.ui.output 'The Fusion metadata for the VM may not be removed completely'
39
+ else
40
+ Fission.ui.output "Either exit the Fusion GUI or use '--force' and try again"
41
+ Fission.ui.output_and_exit "NOTE: Forcing a VM deletion with the Fusion GUI running may not clean up all of the VM metadata", 1
42
+ end
43
+ end
44
+
45
+ Fission::VM.delete target_vm
46
+
47
+ Fission.ui.output ''
48
+ Fission.ui.output "Deletion complete!"
49
+ end
50
+
51
+ def option_parser
52
+ optparse = OptionParser.new do |opts|
53
+ opts.banner = "\ndelete usage: fission delete target_vm [--force]"
54
+
55
+ opts.on '--force', "Stop the VM if it's running and then delete it" do
56
+ @options.force = true
57
+ end
58
+ end
59
+
60
+ optparse
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,47 @@
1
+ module Fission
2
+ class Command
3
+ class SnapshotCreate < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ end
8
+
9
+ def execute
10
+ unless @args.count == 2
11
+ Fission.ui.output self.class.help
12
+ Fission.ui.output ""
13
+ Fission.ui.output_and_exit "Incorrect arguments for snapshot create command", 1
14
+ end
15
+
16
+ vm_name, snap_name = @args.take 2
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 Fission::VM.all_running.include? vm_name
23
+ Fission.ui.output "VM '#{vm_name}' is not running"
24
+ Fission.ui.output_and_exit 'A snapshot cannot be created unless the VM is running', 1
25
+ end
26
+
27
+ @vm = Fission::VM.new vm_name
28
+
29
+ if @vm.snapshots.include? snap_name
30
+ Fission.ui.output_and_exit "VM '#{vm_name}' already has a snapshot named '#{snap_name}'", 1
31
+ end
32
+
33
+ Fission.ui.output "Creating snapshot"
34
+ @vm.create_snapshot(snap_name)
35
+ end
36
+
37
+ def option_parser
38
+ optparse = OptionParser.new do |opts|
39
+ opts.banner = "\nsnapshot create: fission snapshot create my_vm snapshot_1"
40
+ end
41
+
42
+ optparse
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ module Fission
2
+ class Command
3
+ class SnapshotList < 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 snapshot list 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
+ @vm = Fission::VM.new vm_name
23
+ snaps = @vm.snapshots
24
+
25
+ if snaps.any?
26
+ Fission.ui.output snaps.join("\n")
27
+ else
28
+ Fission.ui.output "No snapshots found for VM '#{vm_name}'"
29
+ end
30
+ end
31
+
32
+ def option_parser
33
+ optparse = OptionParser.new do |opts|
34
+ opts.banner = "\nsnapshot list: fission snapshot list my_vm"
35
+ end
36
+
37
+ optparse
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ module Fission
2
+ class Command
3
+ class SnapshotRevert < Command
4
+
5
+ def initialize(args=[])
6
+ super
7
+ end
8
+
9
+ def execute
10
+ unless @args.count == 2
11
+ Fission.ui.output self.class.help
12
+ Fission.ui.output ''
13
+ Fission.ui.output_and_exit 'Incorrect arguments for snapshot revert command', 1
14
+ end
15
+
16
+ vm_name, snap_name = @args.take 2
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 Fission::Fusion.is_running?
23
+ Fission.ui.output 'It looks like the Fusion GUI is currently running'
24
+ Fission.ui.output_and_exit 'Please exit the Fusion GUI and try again', 1
25
+ end
26
+
27
+ @vm = Fission::VM.new vm_name
28
+
29
+ unless @vm.snapshots.include? snap_name
30
+ Fission.ui.output_and_exit "Unable to find the snapshot '#{snap_name}'", 1
31
+ end
32
+
33
+ Fission.ui.output "Reverting to snapshot '#{snap_name}'"
34
+ @vm.revert_to_snapshot(snap_name)
35
+ end
36
+
37
+ def option_parser
38
+ optparse = OptionParser.new do |opts|
39
+ opts.banner = "\nsnapshot revert: fission snapshot revert my_vm snapshot_1"
40
+ end
41
+
42
+ optparse
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -4,16 +4,19 @@ module Fission
4
4
 
5
5
  def initialize(args=[])
6
6
  super
7
+ @options.headless = false
7
8
  end
8
9
 
9
10
  def execute
10
- unless args.count == 1
11
+ option_parser.parse! @args
12
+
13
+ if @args.empty?
11
14
  Fission.ui.output self.class.help
12
15
  Fission.ui.output ""
13
16
  Fission.ui.output_and_exit "Incorrect arguments for start command", 1
14
17
  end
15
18
 
16
- vm_name = args.first
19
+ vm_name = @args.first
17
20
 
18
21
  unless Fission::VM.exists? vm_name
19
22
  Fission.ui.output_and_exit "Unable to find the VM #{vm_name} (#{Fission::VM.path(vm_name)})", 1
@@ -26,12 +29,27 @@ module Fission
26
29
 
27
30
  Fission.ui.output "Starting '#{vm_name}'"
28
31
  @vm = Fission::VM.new vm_name
29
- @vm.start
32
+
33
+ if @options.headless
34
+ if Fission::Fusion.is_running?
35
+ Fission.ui.output 'It looks like the Fusion GUI is currently running'
36
+ Fission.ui.output 'A VM cannot be started in headless mode when the Fusion GUI is running'
37
+ Fission.ui.output_and_exit "Exit the Fusion GUI and try again", 1
38
+ else
39
+ @vm.start :headless => true
40
+ end
41
+ else
42
+ @vm.start
43
+ end
30
44
  end
31
45
 
32
46
  def option_parser
33
47
  optparse = OptionParser.new do |opts|
34
- opts.banner = "\nstart usage: fission start vm"
48
+ opts.banner = "\nstart usage: fission start vm [options]"
49
+
50
+ opts.on '--headless', 'Start the VM in headless mode (i.e. no Fusion GUI console)' do
51
+ @options.headless = true
52
+ end
35
53
  end
36
54
 
37
55
  optparse