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():