netvbox 0.0.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.
data/bin/netvbox ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'netvbox/vm_manager'
4
+ require 'netvbox/config_manager'
5
+ require 'netvbox/version'
6
+
7
+ NETVBOX_CONFIG = "#{ENV['HOME']}/.netvbox"
8
+
9
+ def print_help
10
+ puts "NetVbox version #{NetVbox::VERSION}"
11
+ puts "Current config file: #{NETVBOX_CONFIG}"
12
+ puts 'sub-commands:'
13
+ puts ' add [ssh host] [username] [password] [vm name] [snapshot name]'
14
+ puts ' adds a vm to manage'
15
+ puts ' list'
16
+ puts ' lists vms under management'
17
+ puts ' load'
18
+ puts ' loads vm snapshots'
19
+ puts ' poweroff'
20
+ puts ' powers off all vms'
21
+ puts ' remove [ssh host] [username] [vm name] [snapshot name]'
22
+ puts ' removes a vm from management'
23
+ puts ' status'
24
+ puts ' shows status of vms'
25
+ end
26
+
27
+ def parse_args
28
+ command = ARGV[0]
29
+ config_manager = NetVbox::ConfigManager.new(NETVBOX_CONFIG)
30
+ vm_manager = NetVbox::VmManager.new(config_manager)
31
+ case command
32
+ when 'add'
33
+ if ARGV.length >= 6
34
+ hostname, username, password, vm_name, snapshot_name = ARGV[1..5]
35
+ vm_manager.add_vm(hostname, username, password, vm_name, snapshot_name)
36
+ else
37
+ print_help
38
+ end
39
+ when 'list'
40
+ vm_manager.list_vms
41
+ when 'load'
42
+ vm_manager.load_snapshots
43
+ when 'poweroff'
44
+ vm_manager.poweroff_all
45
+ when 'remove'
46
+ if ARGV.length >= 5
47
+ hostname, username, vm_name, snapshot_name = ARGV[1..4]
48
+ vm_manager.remove_vm(hostname, username, vm_name, snapshot_name)
49
+ else
50
+ print_help
51
+ end
52
+ when 'status'
53
+ vm_manager.print_status
54
+ else
55
+ puts "Unknown command: #{command}"
56
+ print_help
57
+ end
58
+ end
59
+
60
+ if ARGV.empty?
61
+ print_help
62
+ else
63
+ parse_args
64
+ end
@@ -0,0 +1,59 @@
1
+ require 'csv'
2
+ require 'netvbox/vm'
3
+
4
+ module NetVbox
5
+ class ConfigManager
6
+ def initialize(config_file_path)
7
+ @config_file_path = config_file_path
8
+ end
9
+
10
+ def get_all_vm_info
11
+ all_vm_info = []
12
+ if File.readable?(@config_file_path)
13
+ CSV.foreach(@config_file_path) do |row|
14
+ all_vm_info << a_to_vm_info(row)
15
+ end
16
+ end
17
+ all_vm_info
18
+ end
19
+
20
+ def add_vm(vm_info)
21
+ all_vm_info = get_all_vm_info
22
+ all_vm_info.index(vm_info).nil? ? write_vm_info(all_vm_info << vm_info) : false
23
+ end
24
+
25
+ def remove_vm(vm_info)
26
+ all_vm_info = get_all_vm_info
27
+ updated_vm_info = all_vm_info.select {|i| !(i === vm_info)}
28
+ all_vm_info != updated_vm_info ? write_vm_info(updated_vm_info) : false
29
+ end
30
+
31
+ private
32
+
33
+ def vm_info_to_a(vm_info)
34
+ a = []
35
+ a << vm_info.ssh_connection_info.hostname
36
+ a << vm_info.ssh_connection_info.username
37
+ a << vm_info.ssh_connection_info.password
38
+ a << vm_info.vm_name
39
+ a << vm_info.snapshot_name
40
+ a
41
+ end
42
+
43
+ def a_to_vm_info(a)
44
+ VmInfo.new(SshConnectionInfo.new(a[0], a[1], a[2]), a[3], a[4])
45
+ end
46
+
47
+ def write_vm_info(all_vm_info)
48
+ begin
49
+ CSV.open(@config_file_path, "w") do |csv|
50
+ all_vm_info.each {|vm_info| csv << vm_info_to_a(vm_info)}
51
+ end
52
+ true
53
+ rescue IOError
54
+ puts "ERROR: Could not write vm info to #{@config_file_path}"
55
+ return false
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,3 @@
1
+ module NetVbox
2
+ VERSION = "0.0.1"
3
+ end
data/lib/netvbox/vm.rb ADDED
@@ -0,0 +1,110 @@
1
+ require 'net/ssh'
2
+
3
+ module NetVbox
4
+
5
+ class SshConnectionInfo
6
+ attr_reader :hostname, :username, :password
7
+
8
+ def initialize(hostname, username, password)
9
+ @hostname = hostname
10
+ @username = username
11
+ @password = password
12
+ end
13
+
14
+ def ==(other)
15
+ self === other &&
16
+ self.password == other.password
17
+ end
18
+
19
+ def ===(other)
20
+ self.hostname == other.hostname &&
21
+ self.username == other.username
22
+ end
23
+ end
24
+
25
+ class VmInfo
26
+ attr_reader :ssh_connection_info, :vm_name, :snapshot_name
27
+
28
+ def initialize(ssh_connection_info, vm_name, snapshot_name)
29
+ @ssh_connection_info = ssh_connection_info
30
+ @vm_name = vm_name
31
+ @snapshot_name = snapshot_name
32
+ end
33
+
34
+ def ==(other)
35
+ self.ssh_connection_info == other.ssh_connection_info &&
36
+ self.vm_name == other.vm_name &&
37
+ self.snapshot_name == other.snapshot_name
38
+ end
39
+
40
+ def ===(other)
41
+ self.ssh_connection_info === other.ssh_connection_info &&
42
+ self.vm_name == other.vm_name &&
43
+ self.snapshot_name == other.snapshot_name
44
+ end
45
+ end
46
+
47
+ class Vm
48
+ attr_reader :vm_info
49
+
50
+ def initialize(vm_info)
51
+ @vm_info = vm_info
52
+ end
53
+
54
+ def status
55
+ vm_state = showvminfo('VMState')
56
+ case vm_state
57
+ when 'running'
58
+ 'running'
59
+ when 'saved'
60
+ 'not running (saved)'
61
+ when 'poweroff'
62
+ 'not running (power off)'
63
+ when 'aborted'
64
+ 'not running (aborted)'
65
+ else
66
+ vm_state
67
+ end
68
+ end
69
+
70
+ def poweroff
71
+ if showvminfo('VMState') == 'running'
72
+ my_ssh do |ssh|
73
+ ssh.exec!("VBoxManage controlvm \"#{@vm_info.vm_name}\" poweroff").strip
74
+ end
75
+ else
76
+ "#{@vm_info.vm_name} is not running"
77
+ end
78
+ end
79
+
80
+ def load_snapshot
81
+ return "ERROR: you must disable 3d acceleration for #{@vm_info.vm_name}" if showvminfo('accelerate3d') == 'on'
82
+ poweroff
83
+ my_ssh do |ssh|
84
+ ssh.exec!("VBoxManage snapshot \"#{@vm_info.vm_name}\" restore \"#{@vm_info.snapshot_name}\" && VBoxManage startvm \"#{@vm_info.vm_name}\" --type headless")
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def showvminfo(var_name)
91
+ my_ssh do |ssh|
92
+ ssh.exec!("VBoxManage showvminfo \"#{@vm_info.vm_name}\" --machinereadable | grep ^#{var_name}= | cut -d '\"' -f 2").strip
93
+ end
94
+ end
95
+
96
+ def my_ssh
97
+ ssh_info = @vm_info.ssh_connection_info
98
+ begin
99
+ # can raise SocketError or Net::SSH::AuthenticationFailed
100
+ Net::SSH.start(ssh_info.hostname, ssh_info.username, :password => ssh_info.password) do |ssh|
101
+ return yield ssh
102
+ end
103
+ rescue SocketError
104
+ return 'Connection Error'
105
+ rescue Net::SSH::AuthenticationFailed
106
+ return 'Authentication Error'
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,70 @@
1
+ require 'netvbox/vm'
2
+ require 'netvbox/config_manager'
3
+
4
+ module NetVbox
5
+ class VmManager
6
+ def initialize(config_manager)
7
+ @config_manager = config_manager
8
+ end
9
+
10
+ def print_status
11
+ puts 'Getting status info...'
12
+ threads = []
13
+ get_vms.each do |vm|
14
+ threads << Thread.new(vm) {|vm| puts "#{vm.vm_info.vm_name} on #{vm.vm_info.ssh_connection_info.hostname}... #{vm.status}"}
15
+ end
16
+ threads.each(&:join)
17
+ end
18
+
19
+ def load_snapshots
20
+ puts 'Loading snapshots...'
21
+ threads = []
22
+ get_vms.each do |vm|
23
+ threads << Thread.new(vm) {|vm| vm.load_snapshot}
24
+ end
25
+ threads.each(&:join)
26
+ print_status
27
+ end
28
+
29
+ def poweroff_all
30
+ puts 'Powering off vms...'
31
+ threads = []
32
+ get_vms.each do |vm|
33
+ threads << Thread.new(vm) {|vm| vm.poweroff}
34
+ end
35
+ threads.each(&:join)
36
+ print_status
37
+ end
38
+
39
+ def list_vms
40
+ @config_manager.get_all_vm_info.each do |vm_info|
41
+ ssh_info = vm_info.ssh_connection_info
42
+ puts "#{ssh_info.username}@#{ssh_info.hostname} - vm: #{vm_info.vm_name}, snapshot: #{vm_info.snapshot_name}"
43
+ end
44
+ end
45
+
46
+ def add_vm(hostname, username, password, vm_name, snapshot_name)
47
+ vm_info = VmInfo.new(SshConnectionInfo.new(hostname, username, password), vm_name, snapshot_name)
48
+ if @config_manager.add_vm(vm_info)
49
+ puts "Successfully added vm (#{vm_name}, #{snapshot_name})"
50
+ else
51
+ puts "Failed to add vm (#{vm_name}, #{snapshot_name})"
52
+ end
53
+ end
54
+
55
+ def remove_vm(hostname, username, vm_name, snapshot_name)
56
+ vm_info = VmInfo.new(SshConnectionInfo.new(hostname, username, nil), vm_name, snapshot_name)
57
+ if @config_manager.remove_vm(vm_info)
58
+ puts "Successfully removed vm (#{vm_name}, #{snapshot_name})"
59
+ else
60
+ puts "Failed to remove vm (#{vm_name}, #{snapshot_name})"
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def get_vms
67
+ @config_manager.get_all_vm_info.collect {|vm_info| Vm.new(vm_info)}
68
+ end
69
+ end
70
+ end
data/lib/netvbox.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "netvbox/version"
2
+
3
+ module NetVbox
4
+ # nothing yet...
5
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: netvbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dennis Hsu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: net-ssh
16
+ requirement: &12295500 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *12295500
25
+ description: Remote administration of VirtualBox VMs through ssh
26
+ email:
27
+ - hsu.dennis@gmail.com
28
+ executables:
29
+ - netvbox
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/netvbox.rb
34
+ - lib/netvbox/version.rb
35
+ - lib/netvbox/vm_manager.rb
36
+ - lib/netvbox/vm.rb
37
+ - lib/netvbox/config_manager.rb
38
+ - bin/netvbox
39
+ homepage:
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.10
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Remote administration of VirtualBox VMs through ssh
63
+ test_files: []