diff --git a/src/gnome-virt-manager.glade b/src/gnome-virt-manager.glade
index 20588d15..5307531c 100644
--- a/src/gnome-virt-manager.glade
+++ b/src/gnome-virt-manager.glade
@@ -521,6 +521,8 @@ Inactive virtual machines
GTK_WINDOW_TOPLEVEL
GTK_WIN_POS_NONE
False
+ 500
+ 350
True
False
True
@@ -530,6 +532,7 @@ Inactive virtual machines
GDK_GRAVITY_NORTH_WEST
True
False
+
@@ -644,7 +647,7 @@ Inactive virtual machines
-
+
True
True
True
@@ -654,7 +657,8 @@ Inactive virtual machines
False
-
+
+ 3
True
8
3
@@ -663,7 +667,7 @@ Inactive virtual machines
3
-
+
True
<b>Basic Details:</b>
False
@@ -690,7 +694,7 @@ Inactive virtual machines
-
+
True
Name:
False
@@ -718,7 +722,7 @@ Inactive virtual machines
-
+
True
False
True
@@ -740,7 +744,7 @@ Inactive virtual machines
-
+
True
Status:
False
@@ -768,7 +772,7 @@ Inactive virtual machines
-
+
True
CPU usage:
False
@@ -796,7 +800,7 @@ Inactive virtual machines
-
+
True
Memory usage:
False
@@ -824,63 +828,7 @@ Inactive virtual machines
-
- True
- Network usage:
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 10
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- 1
- 6
- 7
- fill
-
-
-
-
-
-
- True
- Disk usage:
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 10
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- 1
- 7
- 8
- fill
-
-
-
-
-
-
+
True
<b>Performance:</b>
False
@@ -908,7 +856,7 @@ Inactive virtual machines
-
+
True
18%
False
@@ -936,7 +884,7 @@ Inactive virtual machines
-
+
True
30 MB of 128 MB
False
@@ -964,7 +912,7 @@ Inactive virtual machines
-
+
True
20 bits/sec
False
@@ -992,7 +940,7 @@ Inactive virtual machines
-
+
True
80 MB of 1 GB
False
@@ -1020,13 +968,13 @@ Inactive virtual machines
-
+
True
False
0
-
+
True
gtk-stop
4
@@ -1043,7 +991,7 @@ Inactive virtual machines
-
+
True
Shut down
False
@@ -1078,7 +1026,7 @@ Inactive virtual machines
-
+
True
0
1
@@ -1096,7 +1044,7 @@ Inactive virtual machines
-
+
True
0
1
@@ -1114,38 +1062,94 @@ Inactive virtual machines
-
+
True
- 0
- 1
- 0
- 1
+ Disk usage:
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 10
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
- 1
- 2
+ 0
+ 1
6
7
fill
- fill
+
-
+
+ True
+ Network usage:
+ False
+ False
+ GTK_JUSTIFY_LEFT
+ False
+ False
+ 0
+ 0.5
+ 10
+ 0
+ PANGO_ELLIPSIZE_NONE
+ -1
+ False
+ 0
+
+
+ 0
+ 1
+ 7
+ 8
+ fill
+
+
+
+
+
+
True
GTK_PROGRESS_LEFT_TO_RIGHT
0.119999997318
0.10000000149
PANGO_ELLIPSIZE_NONE
+
+ 1
+ 2
+ 6
+ 7
+ fill
+
+
+
+
+
+
+ True
+ 0
+ 1
+ 0
+ 1
+
1
2
7
8
fill
-
+ fill
@@ -1156,7 +1160,7 @@ Inactive virtual machines
-
+
True
Overview
False
@@ -1179,478 +1183,11 @@ Inactive virtual machines
-
- True
- False
- 0
-
-
-
- True
- GTK_ORIENTATION_VERTICAL
- GTK_TOOLBAR_BOTH
- True
- True
-
-
-
- True
- CPU
- True
- gtk-refresh
- True
- True
- False
- True
-
-
- False
- True
-
-
-
-
-
- True
- Memory
- True
- gtk-justify-fill
- True
- True
- False
- False
- radiotoolbutton5
-
-
- False
- True
-
-
-
-
-
- True
- Ethernet
- True
- gtk-network
- True
- True
- False
- False
- radiotoolbutton5
-
-
- False
- True
-
-
-
-
-
- True
- Hard drive
- True
- gtk-harddisk
- True
- True
- False
- False
- radiotoolbutton5
-
-
- False
- True
-
-
-
-
-
- True
- Add hardware
- True
- gtk-add
- True
- True
- False
- False
- radiotoolbutton5
-
-
- False
- True
-
-
-
-
- 0
- False
- False
-
-
-
-
-
- True
- False
- True
- GTK_POS_TOP
- False
- False
-
-
-
-
-
-
-
- True
- label22
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- tab
-
-
-
-
-
- True
- False
- 3
-
-
-
- True
- <b>Memory</b>
- False
- True
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- False
- True
-
-
-
-
-
- True
- What is the maximum amount of memory this VM should be able to use?
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- False
- False
-
-
-
-
-
- True
- True
- True
- GTK_POS_TOP
- 1
- GTK_UPDATE_CONTINUOUS
- False
- 0 0 0 0 0 0
-
-
- 0
- False
- True
-
-
-
-
-
- True
- 2
- 2
- False
- 3
- 3
-
-
-
- True
- Current usage:
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- 1
- 0
- 1
- fill
-
-
-
-
-
-
- True
- Total memory on host machine:
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 0
- 1
- 1
- 2
- fill
-
-
-
-
-
-
- True
- 30 MB
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 1
- 2
- 0
- 1
- fill
-
-
-
-
-
-
- True
- 1 GB
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- 1
- 2
- 1
- 2
- fill
-
-
-
-
-
- 0
- False
- False
-
-
-
-
- False
- True
-
-
-
-
-
- True
- label23
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- tab
-
-
-
-
-
-
-
-
-
- True
- label24
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- tab
-
-
-
-
-
-
-
-
-
- True
- label25
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- tab
-
-
-
-
-
-
-
-
-
- True
- label26
- False
- False
- GTK_JUSTIFY_LEFT
- False
- False
- 0.5
- 0.5
- 0
- 0
- PANGO_ELLIPSIZE_NONE
- -1
- False
- 0
-
-
- tab
-
-
-
-
- 0
- True
- True
-
-
-
-
- False
- True
-
+
-
+
True
Hardware
False
diff --git a/src/gnome-virt-manager.py.in b/src/gnome-virt-manager.py.in
index 088cd901..aadf4e2f 100755
--- a/src/gnome-virt-manager.py.in
+++ b/src/gnome-virt-manager.py.in
@@ -45,9 +45,57 @@ class vmmAbout:
class vmmDetails:
- def __init__(self, vmm):
+ def __init__(self, vmm, stats, conf, vmname):
self.window = gtk.glade.XML(asset_dir + "/" + appname + ".glade", "vmm-details")
self.vmm = vmm
+ self.stats = stats
+ self.conf = conf
+ self.vmname = vmname
+
+ topwin = self.window.get_widget("vmm-details")
+ topwin.hide()
+ topwin.set_title(vmname + " " + topwin.get_title())
+
+ self.window.get_widget("overview-name").set_text(vmname)
+
+
+ #self.window.get_widget("overview-cpu-usage-graph").set_curve_type(gtk.CURVE_TYPE_SPLINE)
+ #self.window.get_widget("overview-memory-usage-graph").set_curve_type(gtk.CURVE_TYPE_LINEAR)
+
+ conf.on_stats_history_length_changed(self.change_graph_ranges)
+
+ self.window.signal_autoconnect({
+ "on_vmm_details_delete_event": self.close,
+ })
+
+ self.stats.connect_to_signal("vm_updated", self.refresh_overview)
+ self.refresh_overview(vmname)
+ self.change_graph_ranges()
+
+ def show(self):
+ dialog = self.window.get_widget("vmm-details")
+ dialog.show_all()
+
+ def close(self,ignore1=None,ignore2=None):
+ self.window.get_widget("vmm-details").hide()
+ return 1
+
+ def change_graph_ranges(self, ignore1=None,ignore2=None,ignore3=None,ignore4=None):
+ len = self.conf.get_stats_history_length()
+ self.window.get_widget("overview-cpu-usage-graph").set_range(0, len, 0, 100)
+ self.window.get_widget("overview-memory-usage-graph").set_range(0, len, 0, 100)
+ self.window.get_widget("overview-network-traffic-graph").set_range(0, len, 0, 100)
+
+ def refresh_overview(self, vmname):
+ if not(vmname == self.vmname):
+ return
+
+ self.window.get_widget("overview-status-text").set_text(self.stats.run_status(vmname))
+ self.window.get_widget("overview-status-icon").set_from_pixbuf(self.stats.run_status_icon(vmname))
+ self.window.get_widget("overview-cpu-usage-graph").set_vector(self.stats.cpu_time_vector(vmname))
+ self.window.get_widget("overview-memory-usage-graph").set_vector(self.stats.current_memory_vector(vmname))
+ self.window.get_widget("overview-cpu-usage-text").set_text("%2.2f%%" % self.stats.cpu_time_percentage(vmname))
+ self.window.get_widget("overview-memory-usage-text").set_text("%2.2f MB of %2.2f MB" % (self.stats.current_memory(vmname)/1024, self.stats.host_memory_size()/1024))
class vmmPreferences:
@@ -100,8 +148,10 @@ class vmmManager:
self.stats = vmmStats(self.vmm, self.conf)
self.prepare_vmlist()
+
self.about = None
self.preferences = None
+ self.details = {}
# Setup update timers
self.conf.on_stats_update_interval_changed(self.change_timer_interval)
@@ -131,6 +181,7 @@ class vmmManager:
"on_vm_manager_delete_event": self.exit_app,
"on_menu_file_quit_activate": self.exit_app,
"on_vmm_close_clicked": self.exit_app,
+ "on_vm_details_clicked": self.show_vm_details,
"on_menu_edit_preferences_activate": self.show_preferences,
"on_menu_help_about_activate": self.show_about,
@@ -180,6 +231,20 @@ class vmmManager:
print "Remove " + name
break
+ def current_vm(self):
+ vmlist = self.window.get_widget("vm-list")
+ selection = vmlist.get_selection()
+ active = selection.get_selected()
+ if active[1] != None:
+ return active[0].get_value(active[1], 0)
+ return None
+
+ def show_vm_details(self,ignore):
+ vmname = self.current_vm()
+ if not(self.details.has_key(vmname)):
+ self.details[vmname] = vmmDetails(self.vmm, self.stats, self.conf, vmname)
+
+ self.details[vmname].show()
def change_timer_interval(self,ignore1,ignore2,ignore3,ignore4):
print "Removing timer"
@@ -286,16 +351,6 @@ class vmmManager:
model.set_sort_func(VMLIST_SORT_MEMORY_USAGE, self.vmlist_memory_usage_sorter)
model.set_sort_column_id(VMLIST_SORT_NAME, gtk.SORT_ASCENDING)
- self.vmlist_icons = {
- "blocked": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_blocked.png"),
- "crashed": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_crashed.png"),
- "paused": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_paused.png"),
- "running": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_running.png"),
- "shutdown": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_shutdown.png"),
- "shutoff": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_shutoff.png"),
- "idle": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_idle.png"),
- }
-
#vmlist.set_headers_clickable(True)
# XXX does python have a built-in sort op like perl's <=> / cmp ?
@@ -368,8 +423,7 @@ class vmmManager:
def status_icon(self, column, cell, model, iter, data):
name = model.get_value(iter, 0)
- pb = self.vmlist_icons[self.stats.run_status(name).lower()]
- cell.set_property('pixbuf', pb)
+ cell.set_property('pixbuf', self.stats.run_status_icon(name))
def cpu_usage_text(self, column, cell, model, iter, data):
name = model.get_value(iter, 0)
@@ -488,7 +542,18 @@ class vmmStats:
self.vms = {}
self.hostinfo = vmm.getInfo()
self.conf = conf
- self.callbacks = { "vm_added": [], "vm_removed": [] }
+ self.callbacks = { "vm_added": [], "vm_removed": [], "vm_updated": [] }
+
+ self.status_icons = {
+ "blocked": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_blocked.png"),
+ "crashed": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_crashed.png"),
+ "paused": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_paused.png"),
+ "running": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_running.png"),
+ "shutdown": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_shutdown.png"),
+ "shutoff": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_shutoff.png"),
+ "idle": gtk.gdk.pixbuf_new_from_file(asset_dir + "/pixmaps/state_idle.png"),
+ }
+
def connect_to_signal(self, name, callback):
if not(self.callbacks.has_key(name)):
@@ -496,15 +561,24 @@ class vmmStats:
self.callbacks[name].append(callback)
+ def disconnect_from_signal(self, name, callback):
+ for i in len(self.callbacks[name]):
+ if self.callbacks[i] == callback:
+ del self.callbacks[i:i]
+
+
def notify_vm_added(self, name):
for cb in self.callbacks["vm_added"]:
cb(name)
-
def notify_vm_removed(self, name):
for cb in self.callbacks["vm_removed"]:
cb(name)
+ def notify_vm_updated(self, name):
+ for cb in self.callbacks["vm_updated"]:
+ cb(name)
+
def tick(self):
print "Tick"
doms = self.vmm.listDomainsID()
@@ -531,8 +605,9 @@ class vmmStats:
for name in self.vms.keys():
info = self.vms[name]["handle"].info()
- if len(self.vms[name]["stats"]) > self.conf.get_stats_history_length():
- self.vms[name]["stats"] = self.vms[name]["stats"][0:len(self.vms[name]["stats"])-1]
+ if (len(self.vms[name]["stats"])+1) > self.conf.get_stats_history_length():
+ end = len(self.vms[name]["stats"])
+ del self.vms[name]["stats"][end-1:end]
prevCpuTime = 0
prevTimestamp = 0
@@ -546,7 +621,7 @@ class vmmStats:
pcentCurrMem = info[2] * 100 / self.host_memory_size()
pcentMaxMem = info[1] * 100 / self.host_memory_size()
- newStats = [{ "timestamp": now,
+ newStats = { "timestamp": now,
"status": info[0],
"cpuTime": (info[4]-prevCpuTime),
"cpuTimeAbs": info[4],
@@ -555,10 +630,11 @@ class vmmStats:
"currMemPercent": pcentCurrMem,
"maxMem": info[1],
"maxMemPercent": pcentMaxMem,
- }]
- totalCpuTime = totalCpuTime + newStats[0]["cpuTime"]
- newStats.append(self.vms[name]["stats"])
- self.vms[name]["stats"] = newStats
+ }
+ totalCpuTime = totalCpuTime + newStats["cpuTime"]
+ self.vms[name]["stats"].insert(0, newStats)
+
+ self.notify_vm_updated(name)
def host_memory_size(self):
return self.hostinfo[1]*1024
@@ -586,6 +662,25 @@ class vmmStats:
def cpu_time_percentage(self, name):
return self.vms[name]["stats"][0]["cpuTimePercent"]
+
+ def cpu_time_vector(self, name):
+ vector = []
+ stats = self.vms[name]["stats"]
+ print "Len " + str(len(stats))
+ for i in range(self.conf.get_stats_history_length()):
+ if i < len(stats):
+ vector.append(stats[i]["cpuTimePercent"])
+ else:
+ vector.append(0)
+ return vector
+
+ def current_memory_vector(self, name):
+ vector = []
+ stats = self.vms[name]["stats"]
+ for i in range(len(stats)):
+ vector.append(stats[i]["currMemPercent"])
+ return vector
+
def run_status(self, name):
status = self.vms[name]["stats"][0]["status"]
@@ -605,7 +700,11 @@ class vmmStats:
return "Crashed"
else:
raise "Unknown status code"
-
+
+ def run_status_icon(self, name):
+ status = self.run_status(name)
+ return self.status_icons[status.lower()]
+
# Run me!
def main():