virtop 0.0.11 → 0.0.13
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/virtop +105 -102
- data/lib/libvirt/connect.rb +52 -54
- data/lib/libvirt/domain.rb +37 -37
- data/lib/virtop.rb +5 -5
- data/lib/virtop/table.rb +56 -56
- metadata +6 -6
data/bin/virtop
CHANGED
@@ -2,18 +2,18 @@
|
|
2
2
|
|
3
3
|
# Require uri module and print out exception message if it could not be loaded.
|
4
4
|
begin
|
5
|
-
|
5
|
+
require 'uri'
|
6
6
|
rescue LoadError => e
|
7
|
-
|
8
|
-
|
7
|
+
$stderr.puts e.message
|
8
|
+
exit 1
|
9
9
|
end
|
10
10
|
|
11
11
|
# Require ncurses module and print out instructions howto install it if it could
|
12
12
|
# not be loaded.
|
13
13
|
begin
|
14
|
-
|
14
|
+
require 'ncurses'
|
15
15
|
rescue LoadError
|
16
|
-
|
16
|
+
$stderr.puts <<EOF
|
17
17
|
The Ruby bindings to the ncurses library are missing. The ncurses gem on
|
18
18
|
rubygems.org is not working with Ruby 1.9, so please issue the following
|
19
19
|
commands as superuser to install a working ncurses gem from github.com:
|
@@ -22,12 +22,12 @@ commands as superuser to install a working ncurses gem from github.com:
|
|
22
22
|
gem install elliottcable-ncurses
|
23
23
|
|
24
24
|
EOF
|
25
|
-
|
25
|
+
exit 1
|
26
26
|
end
|
27
27
|
|
28
28
|
# Show some lines of help.
|
29
|
-
if
|
30
|
-
|
29
|
+
if ['-h', '--help'].include? ARGV.first
|
30
|
+
$stderr.puts <<EOF
|
31
31
|
#{$0} [libvirt-uri]
|
32
32
|
|
33
33
|
libvirt-uri is optional. Default is qemu:///system (for the local libvirt
|
@@ -38,118 +38,121 @@ Key bindings:
|
|
38
38
|
1..6 Sort by column number.
|
39
39
|
|
40
40
|
EOF
|
41
|
-
|
41
|
+
exit 1
|
42
42
|
end
|
43
43
|
|
44
44
|
# Require and include virtop module. It will require libvirt.
|
45
|
-
$:.unshift(
|
46
|
-
require
|
45
|
+
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
46
|
+
require 'virtop'
|
47
47
|
include Virtop
|
48
48
|
|
49
49
|
# Connection URL will be qemu:///system if nothing else is given as the first
|
50
50
|
# parameter.
|
51
|
-
if
|
52
|
-
|
51
|
+
if ARGV.size < 1
|
52
|
+
url = 'qemu:///system'
|
53
53
|
else
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
54
|
+
uri = URI.parse ARGV.first
|
55
|
+
|
56
|
+
# Works around a deadlock if path is empty.
|
57
|
+
if uri.scheme == 'qemu+ssh' and uri.path == ''
|
58
|
+
raise Exception.new 'invalid url specified'
|
59
|
+
else
|
60
|
+
url = uri.to_s
|
61
|
+
end
|
62
62
|
end
|
63
63
|
|
64
64
|
# Open the connection to the libvirt ressource or print out error message.
|
65
65
|
begin
|
66
|
-
|
66
|
+
c = Libvirt::open url
|
67
67
|
rescue Libvirt::ConnectionError
|
68
|
-
|
69
|
-
|
68
|
+
$stderr.puts 'connection failed'
|
69
|
+
exit 1
|
70
70
|
end
|
71
71
|
|
72
72
|
# Initialize ncurses context. Clear and print details for each domain in a 10s
|
73
73
|
# interval. Quit on keypress of 'q'.
|
74
74
|
begin
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
75
|
+
n = Ncurses.initscr
|
76
|
+
|
77
|
+
Ncurses.cbreak
|
78
|
+
Ncurses.noecho
|
79
|
+
Ncurses.halfdelay 10
|
80
|
+
|
81
|
+
# Default sorting by first column (domain name).
|
82
|
+
sortBy = 0
|
83
|
+
|
84
|
+
while true
|
85
|
+
Ncurses.clear
|
86
|
+
|
87
|
+
n.intrflush false
|
88
|
+
n.keypad true
|
89
|
+
|
90
|
+
# Add topmost meta information lines to ncurses screen.
|
91
|
+
begin
|
92
|
+
n.addstr(
|
93
|
+
c.hostname.upcase +
|
94
|
+
"\n" +
|
95
|
+
' cores ' + c.cores +
|
96
|
+
' cpus ' + c.cpus +
|
97
|
+
' ghz ' + c.ghz +
|
98
|
+
' arch ' + c.arch +
|
99
|
+
"\n" +
|
100
|
+
' mem ' + c.mem +
|
101
|
+
' free ' + c.memfree +
|
102
|
+
"\n" +
|
103
|
+
' version ' + c.version +
|
104
|
+
"\n\n"
|
105
|
+
)
|
106
|
+
rescue Libvirt::Error
|
107
|
+
end
|
108
|
+
|
109
|
+
# Initialize table (columns).
|
110
|
+
t = Table.new(
|
111
|
+
'NAME',
|
112
|
+
'STATE',
|
113
|
+
'MEM',
|
114
|
+
'MEM_MAX',
|
115
|
+
'CPU_NUM',
|
116
|
+
'CPU_TIME'
|
117
|
+
)
|
118
|
+
|
119
|
+
# Add information of each domain to table.
|
120
|
+
c.domains.each do |d|
|
121
|
+
t.add_row(
|
122
|
+
d.name,
|
123
|
+
d.state,
|
124
|
+
d.mem,
|
125
|
+
d.mem_max,
|
126
|
+
d.cpu_num,
|
127
|
+
d.cpu_time
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Sort table by chosen column.
|
132
|
+
t.sort_by sortBy
|
133
|
+
|
134
|
+
# Convert table to array of padded strings and add them to ncurses
|
135
|
+
# screen.
|
136
|
+
t.format.each do |line|
|
137
|
+
n.addstr line
|
138
|
+
end
|
139
|
+
|
140
|
+
# Wait for single char user input.
|
141
|
+
char = n.getch
|
142
|
+
case char
|
143
|
+
# Key '1' till '6'
|
144
|
+
when 49..54
|
145
|
+
sortBy = char - 49
|
146
|
+
# Key 'q'
|
147
|
+
when 113
|
148
|
+
raise LetsExit
|
149
|
+
end
|
150
|
+
|
151
|
+
n.refresh
|
152
|
+
end
|
150
153
|
rescue LetsExit
|
151
154
|
ensure
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
+
Ncurses.echo
|
156
|
+
Ncurses.cbreak
|
157
|
+
Ncurses.endwin
|
155
158
|
end
|
data/lib/libvirt/connect.rb
CHANGED
@@ -1,58 +1,56 @@
|
|
1
1
|
# Extend Libvirt::Connect with a method which returns all available domains as
|
2
2
|
# an array and several methods to access the host info more easily.
|
3
3
|
class Libvirt::Connect
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
self.libversion.to_s
|
57
|
-
end
|
4
|
+
# Returns array of domain objects.
|
5
|
+
def domains
|
6
|
+
ret = Array.new
|
7
|
+
|
8
|
+
self.list_domains.each do |id|
|
9
|
+
ret.push self.lookup_domain_by_id id
|
10
|
+
end
|
11
|
+
|
12
|
+
ret
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns number of cores as string.
|
16
|
+
def cores
|
17
|
+
self.node_get_info.cores.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns number of CPUs as string.
|
21
|
+
def cpus
|
22
|
+
self.node_get_info.cpus.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns clock speed in GHz.
|
26
|
+
def ghz
|
27
|
+
"%.2f" % (self.node_get_info.mhz / 1000.0)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns CPU architecture.
|
31
|
+
def arch
|
32
|
+
self.node_get_info.model
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns total memory in mebibytes as string.
|
36
|
+
def mem
|
37
|
+
(self.node_get_info.memory / 1024).to_s + 'M'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns memory which is not allocated to virtual machines in mebibytes as
|
41
|
+
# string.
|
42
|
+
def memfree
|
43
|
+
memUsed = 0
|
44
|
+
|
45
|
+
self.domains.each do |domain|
|
46
|
+
memUsed += domain.info.memory
|
47
|
+
end
|
48
|
+
|
49
|
+
((self.node_get_info.memory - memUsed) / 1024).to_s + 'M'
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the libvirt version number.
|
53
|
+
def version
|
54
|
+
self.libversion.to_s
|
55
|
+
end
|
58
56
|
end
|
data/lib/libvirt/domain.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
# Extend Libvirt::Domain with different methods for human readable display of
|
2
2
|
# the domain state.
|
3
3
|
class Libvirt::Domain
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
# Default string representation of domain object is the domain's name.
|
5
|
+
def to_s
|
6
|
+
self.name
|
7
|
+
end
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
# Return state as string symbol.
|
10
|
+
def state
|
11
|
+
case self.info.state
|
12
|
+
when 1
|
13
|
+
">"
|
14
|
+
when 3
|
15
|
+
"||"
|
16
|
+
else
|
17
|
+
"?"
|
18
|
+
end
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
# Return current memory assignment in mebibytes as string.
|
22
|
+
def mem
|
23
|
+
(self.info.memory / 1024).to_s + "M"
|
24
|
+
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
# Return maximum memory assignment in mebibytes as string.
|
27
|
+
def mem_max
|
28
|
+
(self.info.max_mem / 1024).to_s + "M"
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
# Return the number of assigned virtual CPUs as string.
|
32
|
+
def cpu_num
|
33
|
+
self.info.nr_virt_cpu.to_s
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
# Return time the virtual domain's CPU was scheduled as string formatted
|
37
|
+
# d-hh:mm:ss.
|
38
|
+
def cpu_time
|
39
|
+
t = self.info.cpu_time / 10**9
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
s = (t % 60 ).to_s
|
42
|
+
m = (t / 60 % 60 ).to_s
|
43
|
+
h = (t / 60 / 60 % 24 ).to_s
|
44
|
+
d = (t / 60 / 60 / 24 % 365).to_s
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
"%i-%02i:%02i:%02i" % [d, h, m, s]
|
47
|
+
end
|
48
48
|
end
|
data/lib/virtop.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'libvirt'
|
2
2
|
|
3
3
|
module Virtop
|
4
|
-
|
4
|
+
VERSION = '0.0.13'
|
5
5
|
end
|
6
6
|
|
7
|
-
$:.unshift
|
7
|
+
$:.unshift File.dirname(__FILE__)
|
8
8
|
|
9
|
-
Dir.glob(
|
10
|
-
|
9
|
+
Dir.glob($:.first + '/*/*.rb').sort.each do |file|
|
10
|
+
require file
|
11
11
|
end
|
data/lib/virtop/table.rb
CHANGED
@@ -1,62 +1,62 @@
|
|
1
1
|
# Represents a table. Important for column width correction and sorting of rows.
|
2
2
|
class Virtop::Table
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
3
|
+
# Contructor gets table header strings as arguments.
|
4
|
+
def initialize(*args)
|
5
|
+
@header = args
|
6
|
+
@rows = []
|
7
|
+
@widths = [0] * args.size
|
8
|
+
end
|
9
|
+
|
10
|
+
# Adds a row to the table. Number of arguments must equal the number of
|
11
|
+
# columns given by header strings on contruction.
|
12
|
+
def add_row(*args)
|
13
|
+
if args.size != @header.size
|
14
|
+
raise Exception.new 'Wrong column number.'
|
15
|
+
end
|
16
|
+
|
17
|
+
@rows.push args
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sorts the table by a certain column given by it's header string or the
|
21
|
+
# index of the column starting at zero.
|
22
|
+
def sort_by(col)
|
23
|
+
if col.class == String
|
24
|
+
index = @header.index col
|
25
|
+
else
|
26
|
+
index = col.to_i
|
27
|
+
end
|
28
|
+
|
29
|
+
@rows = @rows.sort_by do |row|
|
30
|
+
row[index]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Converts the whole table as array of strings, which are fancy formatted
|
35
|
+
# (mainly for good column widths).
|
36
|
+
def format
|
37
|
+
update_widths!
|
38
|
+
|
39
|
+
a = []
|
40
|
+
|
41
|
+
([@header] + @rows).each do |row|
|
42
|
+
line = ''
|
43
|
+
@header.size.times do |i|
|
44
|
+
line += row[i].to_s.ljust(@widths[i] + 2)
|
45
|
+
end
|
46
|
+
a.push(line + "\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
a
|
50
|
+
end
|
51
51
|
|
52
52
|
private
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
54
|
+
# Saves maximum width per column into the +@header+ array.
|
55
|
+
def update_widths!
|
56
|
+
@header.size.times do |i|
|
57
|
+
([@header] + @rows).each do |row|
|
58
|
+
@widths[i] = row[i].size if @widths[i] < row[i].size
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
62
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 13
|
9
|
+
version: 0.0.13
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- henning mueller
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-01-10 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -57,11 +57,11 @@ extra_rdoc_files: []
|
|
57
57
|
|
58
58
|
files:
|
59
59
|
- bin/virtop
|
60
|
+
- lib/libvirt/connect.rb
|
61
|
+
- lib/libvirt/domain.rb
|
62
|
+
- lib/virtop.rb
|
60
63
|
- lib/virtop/letsexit.rb
|
61
64
|
- lib/virtop/table.rb
|
62
|
-
- lib/virtop.rb
|
63
|
-
- lib/libvirt/domain.rb
|
64
|
-
- lib/libvirt/connect.rb
|
65
65
|
- README.rdoc
|
66
66
|
has_rdoc: true
|
67
67
|
homepage:
|