virtualman 1.1.9 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,8 @@
2
2
 
3
3
  ####Required
4
4
  require 'virtualman'
5
- include Interractive
5
+
6
+ repl = Virtualman::Interactive::REPL.new
6
7
 
7
8
  menu = ["clone","cook","ssh","add","delete","bootify","exit"]
8
9
 
@@ -11,8 +12,11 @@ choice = "0"
11
12
  while choice != "exit"
12
13
  puts "----VirtualMan----"
13
14
  puts "Please select an action to do with your VM."
14
- choice = Menu.unic_run(menu)
15
- Interractive.send(choice)
15
+ choice = Virtualman::Interactive::Menu.unic_run(menu)
16
+
17
+ if choice != "exit"
18
+ repl.send(choice)
19
+ end
16
20
  end
17
21
 
18
22
  puts "Thank you come again!"
@@ -1,5 +1,8 @@
1
- require 'virtualman/menu'
2
- require 'virtualman/vm'
3
- require 'virtualman/vmlister'
4
- require 'virtualman/configuration'
5
- require 'virtualman/interractive'
1
+ module Virtualman
2
+ require 'virtualman/interactive/helper'
3
+ require 'virtualman/interactive/menu'
4
+ require 'virtualman/vm'
5
+ require 'virtualman/vmlister'
6
+ require 'virtualman/interactive/configuration'
7
+ require 'virtualman/interactive/REPL'
8
+ end
@@ -0,0 +1,124 @@
1
+ module Virtualman
2
+ module Interactive
3
+ class REPL
4
+ attr_reader :configuration
5
+
6
+ include Virtualman::Interactive::Helper
7
+
8
+ def initialize
9
+ @configuration = Virtualman::Interactive::Configuration.new
10
+ end
11
+
12
+ def clone
13
+ cloned_vm = self.clone_vm
14
+ self.start_vm(cloned_vm)
15
+ self.configuration.add_cloned_vm(cloned_vm)
16
+ end
17
+
18
+ def cook
19
+ puts "----Cook a clone!----"
20
+ puts "Which VM do you want to cook?"
21
+ role_path = self.configuration.options["role_path"]
22
+ cookbook_path = self.configuration.options["cookbook_path"]
23
+
24
+ selected_vm = self.choose_vm "cloned_vms"
25
+
26
+ puts "Which role do you want to give?"
27
+
28
+ role = self.choose "roles"
29
+
30
+ user="root"
31
+
32
+ if self.start_vm(selected_vm)
33
+ cmd = "ssh #{user}@#{selected_vm.ip} '/usr/local/bin/chef-solo -j #{role_path}#{role["name"]}.json -r #{cookbook_path}'"
34
+ puts cmd
35
+ Kernel.system(cmd)
36
+ end
37
+
38
+ puts "Thanks!"
39
+ end
40
+
41
+ def ssh
42
+ puts "----SSH to cloned VM----"
43
+ puts "Which VM do you want to ssh?"
44
+
45
+ selected_vm = self.choose_vm "cloned_vms"
46
+
47
+ puts "With which user? [root]"
48
+ user = Menu.ask
49
+
50
+ if user.empty?
51
+ user = "root"
52
+ end
53
+
54
+ if self.start_vm(selected_vm)
55
+ cmd = "ssh #{user}@#{selected_vm.ip}"
56
+ Kernel.exec(cmd)
57
+ end
58
+ end
59
+
60
+ def delete
61
+ puts "----Delete a cloned VM----"
62
+ puts "Which VM delete?"
63
+
64
+ selected_vm = self.choose_vm "cloned_vms"
65
+
66
+ puts "!!YOU ARE ABOUT TO DELETE PEMANENTLY DELETE #{selected_vm.name}!!"
67
+ puts "Are you sure? (yes/[no])"
68
+
69
+ choice = Menu.ask
70
+
71
+ if choice == "yes"
72
+ selected_vm.stop!
73
+
74
+ selected_vm.manage("unregistervm","--delete")
75
+
76
+ self.configuration.delete_cloned_vm(selected_vm)
77
+ else
78
+ puts "VM not deleted!"
79
+ end
80
+ end
81
+
82
+ def add
83
+ puts "----Add a VM----"
84
+ puts "Give the path of the OVA file you want to add"
85
+ puts "(An OVA file represents a Virtual Machine)"
86
+
87
+ path = Menu.ask
88
+
89
+ cmd = "VBoxManage import #{path}"
90
+ puts cmd
91
+ `#{cmd}`
92
+
93
+ if $?.exitstatus == 0
94
+ added_vm = Vm.new(File.basename("#{path}",".*"))
95
+ self.configuration.add_cloned_vm(added_vm)
96
+ else
97
+ puts "There was an error during the import"
98
+ end
99
+ end
100
+
101
+ def bootify
102
+ puts "----Start a VM at boot----"
103
+ puts "Initializing bootify...."
104
+ self.init_bootify
105
+ puts "Whcih VM do you want to add to your boot sequence?"
106
+
107
+ selected_vm = self.choose_vm "cloned_vms"
108
+
109
+ puts "We need to shutdown the VM to add to the boot list."
110
+ puts "Do you want to procedd now? (yes/[no])"
111
+
112
+ choice = Menu.ask
113
+
114
+ if choice == "yes"
115
+ selected_vm.stop!
116
+ selected_vm.manage("modifyvm", "--autostart-enabled on", "--autostart-delay 10")
117
+ puts "#{selected_vm.name} added to your boot sequence."
118
+ start_vm selected_vm
119
+ end
120
+ end
121
+
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,55 @@
1
+ require 'yaml'
2
+
3
+ module Virtualman
4
+ module Interactive
5
+ class Configuration
6
+
7
+ attr_reader :options, :filepath
8
+
9
+ def initialize
10
+ @filepath = File.join(ENV['HOME'],'.virtualman.rc.yaml')
11
+
12
+ if File.exists? @filepath
13
+ @options = YAML.load_file(@filepath)
14
+ else
15
+ STDERR.puts("No configuration file found here ~/.vm_to_clone.rc.yaml")
16
+ STDERR.puts("Thanks to create this file before continuing!")
17
+ STDERR.puts "Config file example:"
18
+ STDERR.puts "---"
19
+ STDERR.puts "source_vm:"
20
+ STDERR.puts " - name: Debian"
21
+ STDERR.puts " snapshot: ready to clone!"
22
+ STDERR.puts " - name: Gentoo"
23
+ STDERR.puts " snapshot: almost ready"
24
+ STDERR.puts "role_path: http://path/to/your/role/fodler"
25
+ STDERR.puts "cookbook_path: http://path/to/your/cookbooks.tar.gz"
26
+ STDERR.puts "roles:"
27
+ STDERR.puts "- devtest"
28
+ STDERR.puts "- devtest_jenkins"
29
+ STDERR.puts "- build_pkg_devtest_jenkins"
30
+ Kernel.abort("No configuration file found here ~/.vm_to_clone.rc.yaml")
31
+ end
32
+ end
33
+
34
+ def record_conf(msg)
35
+ File.open(@filepath, "w") {|f| f.write(@options.to_yaml) }
36
+ puts "#{msg} to your configuration file"
37
+ end
38
+
39
+ def add_cloned_vm(vm_cloned)
40
+ if @options["cloned_vms"] != nil
41
+ @options["cloned_vms"] << {"name" => vm_cloned.name}
42
+ else
43
+ @options.merge!({"cloned_vms" => [{"name" => vm_cloned.name}]})
44
+ end
45
+ record_conf("VM #{vm_cloned.name} has been saved")
46
+ end
47
+
48
+ def delete_cloned_vm(vm_cloned)
49
+ @options["cloned_vms"].reject!{|vm| vm == {"name" => vm_cloned.name.gsub(/\"/,'')} }
50
+ record_conf("VM #{vm_cloned.name} has been deleted")
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,209 @@
1
+ module Virtualman
2
+ module Interactive
3
+ module Helper
4
+ require 'fileutils'
5
+ require 'erb'
6
+
7
+ extend self
8
+
9
+ def choose source
10
+
11
+ list = Array.new
12
+ self.configuration.options[source].each do |option|
13
+ list << option["name"]
14
+ end
15
+ list << "exit"
16
+
17
+ choice = Menu.unic_run(list)
18
+
19
+ exit 0 if choice == "exit"
20
+
21
+ self.configuration.options[source].each_with_index do |option,index|
22
+ if option["name"] == choice
23
+ return self.configuration.options[source][index]
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ #Source can be either source_vms or clonned_vms
30
+ def choose_vm source
31
+ vm_choice = choose source
32
+ return Vm.new("#{vm_choice["name"]}")
33
+
34
+ end
35
+
36
+ def clone_vm
37
+ puts "----Clone_VM----"
38
+ puts "Which VM do you want to clone?"
39
+
40
+ vm_choice = choose "source_vms"
41
+ vm_to_clone = Vm.new("\"#{vm_choice["name"]}\"")
42
+
43
+ puts "How do you want to name your freshly spawned VM?"
44
+ vm_name = Menu.ask
45
+
46
+ options = "--snapshot \"#{vm_choice["snapshot"]}\" --name \"#{vm_name}\" --register"
47
+ vm_to_clone.manage("clonevm", options)
48
+ vm_cloned = Vm.new(vm_name)
49
+ return vm_cloned
50
+ end
51
+
52
+ def start_vm(vm)
53
+ if !vm.running?
54
+ puts "Do you want to start the VM? headless?"
55
+ puts "(default is no)"
56
+ puts "yes/headless/[no]"
57
+
58
+ answer = Menu.ask
59
+
60
+ if answer == "headless"
61
+ option = "--type headless"
62
+ puts "The VM is booting headless"
63
+ elsif answer == "yes"
64
+ option = ""
65
+ puts "The VM is booting"
66
+ else
67
+ puts "The vm will not be started"
68
+ return false
69
+ end
70
+
71
+ vm.manage("startvm", option)
72
+
73
+ Kernel.print "Waiting for the VM to get an IP"
74
+ while !vm.ip
75
+ Kernel.print "."
76
+ Kernel.sleep (1)
77
+ end
78
+ Kernel.print "\n"
79
+ end
80
+
81
+ return vm.running?
82
+ end
83
+
84
+
85
+
86
+ def check_chmod_script
87
+ script = "/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostartDarwin.sh"
88
+ permission = Kernel.sprintf("%o", File.world_readable?(script) )
89
+ if permission != "744"
90
+ puts "Changing file permission of #{script}, to allow it to be executable"
91
+ puts "Thanks to provide your admin password."
92
+ File.chmod(0744, script)
93
+ end
94
+ end
95
+
96
+ def integrate_template filename, path, template_string, *variables
97
+ template = ERB.new(template_string, 0, "%<>")
98
+
99
+ templated = template.result(binding)
100
+
101
+ File.open("/tmp/#{filename}", 'w') { |file| file.write(templated) }
102
+
103
+ if File.exist?(path+filename)
104
+ diff = `diff #{path}#{filename} /tmp/#{filename}`
105
+ result = $?
106
+ if result != 0
107
+ puts "We are trying to install the previous file but there are differences"
108
+ puts "here are the differences"
109
+ puts "#{diff}"
110
+ puts "Do you want to override the original?"
111
+ puts "yes/[no]"
112
+
113
+ answer = Menu.ask
114
+
115
+ if answer != "yes"
116
+ return false
117
+ end
118
+ else
119
+ return true
120
+ end
121
+ end
122
+
123
+ puts "Installing the file #{path}#{filename}..."
124
+ puts "Please povide your password :"
125
+
126
+ output = `sudo cp /tmp/#{filename} #{path}#{filename}`
127
+ result = $?
128
+ if result == 0
129
+ return true
130
+ else
131
+ Kernel.abort(output)
132
+ end
133
+ end
134
+
135
+ def check_plist_file
136
+ puts "Checking plist file..."
137
+ plist_file = "org.virtualbox.vboxautostart.plist"
138
+ plist_path = "/Library/LaunchDaemons/"
139
+
140
+ plist_template = %q{
141
+ <?xml version="1.0" encoding="UTF-8"?>
142
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
143
+ <plist version="1.0">
144
+ <dict>
145
+ <key>Disabled</key>
146
+ <false/>
147
+ <key>KeepAlive</key>
148
+ <false/>
149
+ <key>Label</key>
150
+ <string>org.virtualbox.vboxautostart</string>
151
+ <key>ProgramArguments</key>
152
+ <array>
153
+ <string>/Applications/VirtualBox.app/Contents/MacOS/VBoxAutostartDarwin.sh</string>
154
+ <string>--start</string>
155
+ <string>/etc/vbox/autostart.cfg</string>
156
+ </array>
157
+ <key>RunAtLoad</key>
158
+ <true/>
159
+ <key>debug</key>
160
+ <true/>
161
+ </dict>
162
+ </plist>
163
+ }
164
+
165
+ if self.integrate_template(plist_file, plist_path, plist_template)
166
+ puts "loading the plist file"
167
+ puts "Thanks to provide your admin password."
168
+ `sudo launchctl load #{plist_path}#{plist_file}`
169
+ end
170
+ end
171
+
172
+
173
+ def check_conf_file
174
+ puts "Checking conf file..."
175
+ conf_file = "autostart.cfg"
176
+ conf_path = "/etc/vbox/"
177
+
178
+ conf_template = %q{
179
+ # Default policy is to deny starting a VM, the other option is "allow".
180
+ default_policy = deny
181
+
182
+ # <%= variables[0] %> is allowed to start virtual machines but starting them
183
+ # will be delayed for 10 seconds
184
+ <%= variables[0] %> = {
185
+ allow = true
186
+ startup_delay = 10
187
+ }
188
+ }.gsub(/^ /, '')
189
+
190
+ username = `whoami`.strip
191
+
192
+ integrate_template(conf_file, conf_path, conf_template, username)
193
+ end
194
+
195
+ def init_bootify
196
+
197
+ #check plist file
198
+ check_plist_file
199
+
200
+ #Check chmod of the bash script
201
+ check_chmod_script
202
+
203
+ #Check the conf file
204
+ check_conf_file
205
+
206
+ end
207
+ end
208
+ end
209
+ end
@@ -23,34 +23,41 @@
23
23
 
24
24
  #Forked from https://github.com/cldwalker/menu
25
25
 
26
- module Menu
27
- extend self
26
+ module Virtualman
27
+ module Interactive
28
+ module Menu
29
+ extend self
30
+
31
+ def ask
32
+ $stdin.reopen '/dev/tty'
33
+ $stdin.gets.chomp
34
+ end
35
+
36
+ def unic_prompt(lines)
37
+ ljust_size = lines.size.to_s.size + 1
38
+ lines.each_with_index {|obj,i|
39
+ puts "#{i+1}.".ljust(ljust_size) + " " +obj
40
+ }
41
+ print "\nSpecify your choice\nChoose: "
42
+ end
43
+
44
+ def unic_answer(array, input)
45
+ if input[/(\d+)/]
46
+ index = input.to_i - 1
47
+ if array[index]
48
+ return array[index]
49
+ end
50
+ end
51
+
52
+ Kernel.abort "#{input} is an invalid choice."
53
+ end
54
+
55
+ def unic_run(array)
56
+ unic_prompt(array)
57
+ answer = ask
58
+ return unic_answer(array, answer)
59
+ end
28
60
 
29
- def ask
30
- $stdin.reopen '/dev/tty'
31
- $stdin.gets.chomp
32
- end
33
-
34
- def unic_run(array)
35
- unic_prompt(array)
36
- answer = ask
37
- return unic_answer(array, answer)
38
- end
39
-
40
- def unic_answer(array, input)
41
- if input[/(\d+)/]
42
- index = $1.to_i - 1
43
- return array[index] if array[index]
44
- else
45
- abort("`#{input}' is an invalid choice.")
46
61
  end
47
62
  end
48
-
49
- def unic_prompt(lines)
50
- ljust_size = lines.size.to_s.size + 1
51
- lines.each_with_index {|obj,i|
52
- puts "#{i+1}.".ljust(ljust_size) + " " +obj
53
- }
54
- print "\nSpecify your choice\nChoose: "
55
- end
56
63
  end
@@ -1,62 +1,65 @@
1
- # Implement a way to interact with the VirtualBox command line tool.
2
- # Each #Vm is a Class that contains the #name of the VM. With that
3
- # name you can then interact with it through VBoxManage for example
1
+ module Virtualman
2
+ # Implement a way to interact with the VirtualBox command line tool.
3
+ # Each #Vm is a Class that contains the #name of the VM. With that
4
+ # name you can then interact with it through VBoxManage for example
4
5
 
5
- class Vm
6
+ class Vm
6
7
 
7
- # This attribute contains the name of the VM in VirtualBox.
8
- attr_reader :name
8
+ # This attribute contains the name of the VM in VirtualBox.
9
+ attr_reader :name
9
10
 
10
- # A #Vm is just described by it's name.
11
- # *type is for further needs
12
- def initialize(vm_name, *type)
13
- @name = vm_name
14
- end
15
-
16
- # Returns a boolean whether the VM is running or not
17
- def running?
18
- !`VBoxManage showvminfo #{name} | grep State | grep running`.empty?
19
- end
20
-
21
- # A general method to interact with the VM.
22
- # action is the kind of action to request to VBoxManage
23
- # *param is a list of options
24
- def manage(action, *param)
25
- puts "VBoxManage #{action} #{@name} #{param.join(" ")}"
26
- puts `VBoxManage #{action} #{@name} #{param.join(" ")}`
27
- end
11
+ # A #Vm is just described by it's name.
12
+ # *type is for further needs
13
+ def initialize(vm_name, *type)
14
+ @name = vm_name
15
+ end
28
16
 
29
- # A method to stop properly a vm
30
- # It assumes that you have the name of the VM on your personnal hosts file or DNS
31
- # It can be modified to use GuestAdditions instead
32
- def stop!
33
- $stdout.sync = true
34
- if self.running?
35
- `ssh root@#{self.ip} "shutdown -h now"`
36
- puts "Waiting for complete shutdown of #{self.name}"
37
- while self.running?
38
- print "."
39
- sleep (1)
17
+ # A general method to interact with the VM.
18
+ # action is the kind of action to request to VBoxManage
19
+ # *param is a list of options
20
+ def manage(action, *param)
21
+ #puts "VBoxManage #{action} #{@name} #{param.join(" ")}"
22
+ output = `VBoxManage #{action} \"#{@name}\" #{param.join(" ")} 2>&1`
23
+ if $?.exitstatus != 0
24
+ Kernel.abort(output)
25
+ else
26
+ return output
40
27
  end
41
- sleep (5)
42
28
  end
43
29
 
44
- end
30
+ # Returns a boolean whether the VM is running or not
31
+ def running?
32
+ return !self.manage("showvminfo").split("\n").grep(/running/).empty?
33
+ end
45
34
 
46
- # return the ip of the VM if it is running. O if it is not.
47
- def ip
48
- if self.running?
49
- options = "enumerate #{self.name} | grep IP | cut -d , -f 2 | cut -d : -f 2"
50
- cmd_ip = "VBoxManage guestproperty #{options}"
51
- ip = `#{cmd_ip}`.strip
52
- if ip.match /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/
53
- return ip
35
+ # return the ip of the VM if it is running. O if it is not or if the ip is not correct.
36
+ def ip
37
+ if self.running?
38
+ ip = self.manage("guestproperty enumerate").split("\n").grep(/IP/)[0].split(",")[1].sub(/^ value: /, '')
39
+ if ip.match /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/
40
+ return ip
41
+ else
42
+ return false
43
+ end
54
44
  else
45
+ puts "The VM is not running, cannot determine IP"
55
46
  return false
56
47
  end
57
- else
58
- puts "The VM is not running, cannot determine IP"
59
- return false
48
+ end
49
+
50
+ # A method to stop properly a vm
51
+ # It assumes that you can access to the VM with root and ssh_keys
52
+ def stop!
53
+ if self.running?
54
+ `ssh root@#{self.ip} "shutdown -h now"`
55
+ print "Waiting for complete shutdown of #{self.name}"
56
+ while self.running?
57
+ print "."
58
+ sleep (1)
59
+ end
60
+ sleep (5)
61
+ print("\n")
62
+ end
60
63
  end
61
64
  end
62
65
  end
@@ -1,58 +1,60 @@
1
- # Create an array that contains all the #Vm from VirtualBox
2
- # And implement methods to play with it as a whole.
3
- class VmLister < Array
4
-
5
- # Return an array with the list returned by the command "VBoxManage list vms"
6
- # The argument *type will be used later (to specify a remote host for instance)
7
- def perform_list(*type)
8
- vm_list = `VBoxManage list vms`.split(/\n/).collect {|e| e[/".*"/]}
9
- return vm_list
10
- end
1
+ module Virtualman
2
+ # Create an array that contains all the #Vm from VirtualBox
3
+ # And implement methods to play with it as a whole.
4
+ class VmLister < Array
5
+
6
+ # Return an array with the list returned by the command "VBoxManage list vms"
7
+ # The argument *type will be used later (to specify a remote host for instance)
8
+ def perform_list(*type)
9
+ vm_list = `VBoxManage list vms`.split(/\n/).collect {|e| e[/".*"/]}
10
+ return vm_list
11
+ end
11
12
 
12
- # Populate the array with the method perform_list
13
- # The argument *type will be used later (to specify a remote host for instance)
14
- def populate!(*type)
15
- self.perform_list.each {|vm| self << Vm.new(vm)}
16
- end
13
+ # Populate the array with the method perform_list
14
+ # The argument *type will be used later (to specify a remote host for instance)
15
+ def populate!(*type)
16
+ self.perform_list.each {|vm| self << Vm.new(vm)}
17
+ end
17
18
 
18
- # A simple lister
19
- def list
20
- self.each {|vm| puts "#{vm.name}"}
21
- end
19
+ # A simple lister
20
+ def list
21
+ self.each {|vm| puts "#{vm.name}"}
22
+ end
22
23
 
23
- # Get the IP of each running vm.
24
- def ip
25
- self.each {|vm| puts vm.ip}
26
- end
24
+ # Get the IP of each running vm.
25
+ def ip
26
+ self.each {|vm| puts vm.ip}
27
+ end
27
28
 
28
- # This methods returns a #VmLister object but just with the running VMs of the list.
29
- def running?
30
- running_vms = VmLister.new
31
- self.collect {|vm| running_vms << vm if vm.running?}
32
- return running_vms
33
- end
29
+ # This methods returns a #VmLister object but just with the running VMs of the list.
30
+ def running?
31
+ running_vms = VmLister.new
32
+ self.collect {|vm| running_vms << vm if vm.running?}
33
+ return running_vms
34
+ end
34
35
 
35
- # A general method to interact with the VBoxManage tool
36
- # the block param could be useful for advanced links between your script and this class
37
- def manage(action, *param, &block)
38
- self.each do |vm|
39
- block_param = block.call(vm.name) if block_given?
36
+ # A general method to interact with the VBoxManage tool
37
+ # the block param could be useful for advanced links between your script and this class
38
+ def manage(action, *param, &block)
39
+ self.each do |vm|
40
+ block_param = block.call(vm.name) if block_given?
40
41
 
41
- vm.manage(action, param, block_param)
42
+ vm.manage(action, param, block_param)
43
+ end
42
44
  end
43
- end
44
45
 
45
- # A method to automatically export the list of VMs
46
- def backup!(folder)
47
- self.each {|vm| vm.stop!}
48
- sleep (5)
46
+ # A method to automatically export the list of VMs
47
+ def backup!(folder)
48
+ self.each {|vm| vm.stop!}
49
+ sleep (5)
49
50
 
50
- self.each do |vm|
51
- filename = Time.now().strftime("#{vm.name.delete "\""}_%Y%m%dT%H%M")
52
- vm.manage("export","-o #{folder}/#{filename}.ova")
53
- sleep(5)
54
- end
51
+ self.each do |vm|
52
+ filename = Time.now().strftime("#{vm.name.delete "\""}_%Y%m%dT%H%M")
53
+ vm.manage("export","-o #{folder}/#{filename}.ova")
54
+ sleep(5)
55
+ end
55
56
 
56
- self.each {|vm| vm.manage("startvm", "--type headless")}
57
+ self.each {|vm| vm.manage("startvm", "--type headless")}
58
+ end
57
59
  end
58
- end
60
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: virtualman
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.9
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,9 +9,9 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-06 00:00:00.000000000 Z
12
+ date: 2012-11-15 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: An interactive tool to manage quickly your VMs
14
+ description: An interactive tool, and library to manage quickly your VMs
15
15
  email: pierre.ozoux@gmail.com
16
16
  executables:
17
17
  - virtualman
@@ -19,11 +19,12 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - lib/virtualman.rb
22
- - lib/virtualman/configuration.rb
23
- - lib/virtualman/interractive.rb
24
- - lib/virtualman/menu.rb
22
+ - lib/virtualman/interactive/configuration.rb
23
+ - lib/virtualman/interactive/REPL.rb
24
+ - lib/virtualman/interactive/menu.rb
25
25
  - lib/virtualman/vm.rb
26
26
  - lib/virtualman/vmlister.rb
27
+ - lib/virtualman/interactive/helper.rb
27
28
  - bin/virtualman
28
29
  homepage: http://rubygems.org/gems/virtualman
29
30
  licenses: []
@@ -1,51 +0,0 @@
1
- require 'yaml'
2
-
3
- module Configuration
4
-
5
- def config_file
6
- File.join(ENV['HOME'],'.virtualman.rc.yaml')
7
- end
8
-
9
- def load_conf
10
- if File.exists? config_file
11
- config_options = YAML.load_file(config_file)
12
- else
13
- STDERR.puts "No configuration file found here ~/.vm_to_clone.rc.yaml"
14
- STDERR.puts "Config file example:"
15
- STDERR.puts "---"
16
- STDERR.puts "source_vm:"
17
- STDERR.puts " - name: Debian"
18
- STDERR.puts " snapshot: ready to clone!"
19
- STDERR.puts " - name: Gentoo"
20
- STDERR.puts " snapshot: almost ready"
21
- STDERR.puts "role_path: http://path/to/your/role/fodler"
22
- STDERR.puts "cookbook_path: http://path/to/your/cookbooks.tar.gz"
23
- STDERR.puts "roles:"
24
- STDERR.puts "- devtest"
25
- STDERR.puts "- devtest_jenkins"
26
- STDERR.puts "- build_pkg_devtest_jenkins"
27
- end
28
- return config_options
29
- end
30
-
31
- def record_conf(vm_cloned, *param)
32
- conf = load_conf()
33
-
34
- if param[0] == "delete"
35
- verb = "deleted"
36
- conf["cloned_vms"].reject!{|vm| vm == {"name" => vm_cloned.name.gsub(/\"/,'')} }
37
- else
38
- verb = "saved"
39
-
40
- if conf["cloned_vms"]
41
- conf["cloned_vms"] << {"name" => vm_cloned.name}
42
- else
43
- conf.merge!({"cloned_vms" => {"name" => vm_cloned.name}})
44
- end
45
- end
46
-
47
- File.open(config_file, "w") {|f| f.write(conf.to_yaml) }
48
- puts "VM #{vm_cloned.name} has been #{verb} in your configuration file."
49
- end
50
-
51
- end
@@ -1,226 +0,0 @@
1
- require 'open3'
2
- require 'erb'
3
-
4
- module Interractive
5
- include Configuration
6
-
7
- def choosed_option(array,choice,attribute_to_check)
8
- array.each_with_index do |option,index|
9
- if option[attribute_to_check] == choice
10
- return array[index]
11
- end
12
- end
13
- end
14
-
15
- def choose options, *attribute_to_check
16
- options_array = Configuration.load_conf[options]
17
- if attribute_to_check.empty?
18
- return Menu.unic_run(options_array)
19
- else
20
- list = Array.new
21
- options_array.each do |option|
22
- list << option[attribute_to_check[0]]
23
- end
24
- list << "exit"
25
-
26
- choice = Menu.unic_run(list)
27
-
28
- exit 0 if choice == "exit"
29
-
30
- return choosed_option(options_array,choice,attribute_to_check[0])
31
- end
32
- end
33
-
34
- def choose_vm source
35
- vm_choice = choose source, "name"
36
- vm_choosed = Vm.new("\"#{vm_choice["name"]}\"")
37
- return vm_choosed
38
- end
39
-
40
- def clone_vm
41
- puts "----Clone_VM----"
42
- puts "Which VM do you want to clone?"
43
-
44
- vm_choice = choose "source_vms", "name"
45
- vm_to_clone = Vm.new("\"#{vm_choice["name"]}\"")
46
-
47
- puts "How do you want to name your freshly spawned VM?"
48
- vm_name = Menu.ask
49
-
50
- options = "--snapshot \"#{vm_choice["snapshot"]}\" --name \"#{vm_name}\" --register"
51
- vm_to_clone.manage("clonevm", options)
52
-
53
- vm_cloned = Vm.new(vm_name)
54
- return vm_cloned
55
- end
56
-
57
- def start_vm(vm)
58
- if !vm.running?
59
- puts "Do you want to start the VM? headless?"
60
- puts "(default is no)"
61
- puts "yes/headless/[no]"
62
-
63
- answer = Menu.ask
64
-
65
- if answer == "headless"
66
- option = "--type headless"
67
- puts "The VM is booting headless"
68
- elsif answer == "yes"
69
- option = ""
70
- puts "The VM is booting"
71
- else
72
- puts "The vm will not be started"
73
- return vm
74
- end
75
-
76
- vm.manage("startvm", option)
77
-
78
- print "Waiting for the VM to get an IP"
79
- while !vm.ip
80
- print "."
81
- sleep (1)
82
- end
83
- print "\n"
84
- end
85
-
86
- return vm.running?
87
- end
88
-
89
- def clone
90
- cloned_vm = clone_vm
91
- start_vm(cloned_vm)
92
- record_conf(cloned_vm)
93
- end
94
-
95
- def cook
96
- puts "----Cook a clone!----"
97
- puts "Which VM do you want to cook?"
98
- role_path = load_conf["role_path"]
99
- cookbook_path = load_conf["cookbook_path"]
100
-
101
- selected_vm = choose_vm "cloned_vms"
102
-
103
- puts "Which role do you want to give?"
104
-
105
- role = choose "roles"
106
-
107
- user="root"
108
-
109
- if start_vm(selected_vm)
110
- cmd = "ssh #{user}@#{selected_vm.ip} '/usr/local/bin/chef-solo -j #{role_path}#{role}.json -r #{cookbook_path}'"
111
- p cmd
112
- system(cmd)
113
- end
114
-
115
- puts "Thanks!"
116
- end
117
-
118
- def ssh
119
- puts "----SSH to cloned VM----"
120
- puts "Which VM do you want to ssh?"
121
-
122
- selected_vm = choose_vm "cloned_vms"
123
-
124
- puts "With which user? [root]"
125
- user = Menu.ask
126
-
127
- if user.empty?
128
- user = "root"
129
- end
130
-
131
- if start_vm(selected_vm)
132
- cmd = "ssh #{user}@#{selected_vm.ip}"
133
- exec (cmd)
134
- end
135
- end
136
-
137
- def delete
138
- puts "----Delete a cloned VM----"
139
- puts "Which VM delete?"
140
-
141
- selected_vm = choose_vm "cloned_vms"
142
-
143
- puts "!!YOU ARE ABOUT TO DELETE PEMANENTLY DELETE #{selected_vm.name}!!"
144
- puts "Are you sure? (yes/[no])"
145
-
146
- choice = Menu.ask
147
-
148
- if choice == "yes"
149
- selected_vm.stop!
150
-
151
- selected_vm.manage("unregistervm","--delete")
152
-
153
- record_conf(selected_vm, "delete")
154
- end
155
- end
156
-
157
- def add
158
- puts "----Add a VM----"
159
- puts "Give the path of the OVA file you want to add"
160
- puts "(An OVA file represents a Virtual Machine)"
161
-
162
- path = Menu.ask
163
-
164
- cmd = "VBoxManage import #{path}"
165
- p cmd
166
- system(cmd)
167
-
168
- added_vm = Vm.new(File.basename("#{path}",".*"))
169
- record_conf(added_vm)
170
- end
171
-
172
- def bootify
173
- puts "----Start a VM at boot----"
174
- puts "Whcih VM do you want to add to your boot sequence?"
175
-
176
- selected_vm = choose_vm "cloned_vms"
177
-
178
- # Create template.
179
- template_plist = %q{
180
- <?xml version="1.0" encoding="UTF-8"?>
181
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
182
- <plist version="1.0">
183
- <dict>
184
- <key>Label</key>
185
- <string>org.virtualman.<%= vmname %></string>
186
- <key>ProgramArguments</key>
187
- <array>
188
- <string>VBoxManage</string>
189
- <string>startvm</string>
190
- <string><%= vmname %></string>
191
- <string>--type</string>
192
- <string>headless</string>
193
- </array>
194
- <key>RunAtLoad</key>
195
- <true/>
196
- <key>UserName</key>
197
- <string><%= username %></string>
198
- <key>debug</key>
199
- <true/>
200
- </dict>
201
- </plist>
202
- }.gsub(/^ /, '')
203
-
204
- plist = ERB.new(template_plist, 0, "%<>")
205
-
206
- # Set up template data.
207
-
208
- vmname = selected_vm.name.gsub(/\"/,'')
209
- username = `whoami`.strip
210
-
211
- # Produce result.
212
-
213
- vm_plist = plist.result(binding)
214
-
215
- plist_filename = "org.virtualman.#{vmname}.plist"
216
- tmp_file = "/tmp/#{plist_filename}"
217
- path = "/Library/LaunchDaemons/"
218
-
219
- File.open(tmp_file, 'w') { |file| file.write(vm_plist) }
220
-
221
- `sudo cp #{tmp_file} #{path};sudo launchctl load #{path}#{plist_filename}`
222
-
223
- puts "#{vmname} added to your boot sequence."
224
- end
225
-
226
- end