Added preferences via GConf

This commit is contained in:
berrange@roquette.boston.redhat.com 2006-03-29 05:35:11 -05:00
parent 3ed0ef3458
commit 1b6e7727dd
2 changed files with 684 additions and 96 deletions

View File

@ -3,7 +3,7 @@
<glade-interface> <glade-interface>
<widget class="GtkWindow" id="vm-manager"> <widget class="GtkWindow" id="vmm-manager">
<property name="visible">True</property> <property name="visible">True</property>
<property name="title" translatable="yes">Virtual Machine Manager</property> <property name="title" translatable="yes">Virtual Machine Manager</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="type">GTK_WINDOW_TOPLEVEL</property>
@ -83,7 +83,7 @@
<child> <child>
<widget class="GtkImageMenuItem" id="menu_edit_details"> <widget class="GtkImageMenuItem" id="menu_edit_details">
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">Details</property> <property name="label" translatable="yes">VM details</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_menu_edit_details_activate" last_modification_time="Tue, 28 Mar 2006 17:06:34 GMT"/> <signal name="activate" handler="on_menu_edit_details_activate" last_modification_time="Tue, 28 Mar 2006 17:06:34 GMT"/>
@ -109,6 +109,21 @@
<signal name="activate" handler="on_menu_edit_delete_activate" last_modification_time="Tue, 28 Mar 2006 17:06:34 GMT"/> <signal name="activate" handler="on_menu_edit_delete_activate" last_modification_time="Tue, 28 Mar 2006 17:06:34 GMT"/>
</widget> </widget>
</child> </child>
<child>
<widget class="GtkSeparatorMenuItem" id="separator2">
<property name="visible">True</property>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="menu_edit_preferences">
<property name="visible">True</property>
<property name="label">gtk-preferences</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_menu_edit_preferences_activate" last_modification_time="Wed, 29 Mar 2006 09:57:25 GMT"/>
</widget>
</child>
</widget> </widget>
</child> </child>
</widget> </widget>
@ -301,6 +316,7 @@ Inactive virtual machines</property>
<child> <child>
<widget class="GtkButton" id="vm-delete"> <widget class="GtkButton" id="vm-delete">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_default">True</property> <property name="can_default">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="label">gtk-delete</property> <property name="label">gtk-delete</property>
@ -327,6 +343,7 @@ Inactive virtual machines</property>
<child> <child>
<widget class="GtkButton" id="vm-details"> <widget class="GtkButton" id="vm-details">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_default">True</property> <property name="can_default">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property> <property name="relief">GTK_RELIEF_NORMAL</property>
@ -402,6 +419,7 @@ Inactive virtual machines</property>
<child> <child>
<widget class="GtkButton" id="vm-open"> <widget class="GtkButton" id="vm-open">
<property name="visible">True</property> <property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_default">True</property> <property name="can_default">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="label">gtk-open</property> <property name="label">gtk-open</property>
@ -471,9 +489,9 @@ Inactive virtual machines</property>
</child> </child>
</widget> </widget>
<widget class="GtkAboutDialog" id="vm-about"> <widget class="GtkAboutDialog" id="vmm-about">
<property name="visible">True</property> <property name="visible">True</property>
<property name="destroy_with_parent">True</property> <property name="destroy_with_parent">False</property>
<property name="name" translatable="yes">Virtual Machine Manager</property> <property name="name" translatable="yes">Virtual Machine Manager</property>
<property name="copyright" translatable="yes">Copyright (C) 2006 Red Hat Inc.</property> <property name="copyright" translatable="yes">Copyright (C) 2006 Red Hat Inc.</property>
<property name="comments" translatable="yes"></property> <property name="comments" translatable="yes"></property>
@ -494,9 +512,10 @@ Inactive virtual machines</property>
<property name="wrap_license">False</property> <property name="wrap_license">False</property>
<property name="authors">Daniel P. Berrange &lt;berrange@redhat.com&gt;</property> <property name="authors">Daniel P. Berrange &lt;berrange@redhat.com&gt;</property>
<property name="translator_credits" translatable="yes" comments="TRANSLATORS: Replace this string with your names, one name per line.">translator-credits</property> <property name="translator_credits" translatable="yes" comments="TRANSLATORS: Replace this string with your names, one name per line.">translator-credits</property>
<signal name="delete_event" handler="on_vmm_about_delete_event" last_modification_time="Wed, 29 Mar 2006 10:31:19 GMT"/>
</widget> </widget>
<widget class="GtkWindow" id="vm-details"> <widget class="GtkWindow" id="vmm-details">
<property name="visible">True</property> <property name="visible">True</property>
<property name="title" translatable="yes">Virtual Machine Details</property> <property name="title" translatable="yes">Virtual Machine Details</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property> <property name="type">GTK_WINDOW_TOPLEVEL</property>
@ -1740,4 +1759,305 @@ Inactive virtual machines</property>
</child> </child>
</widget> </widget>
<widget class="GtkDialog" id="vmm-preferences">
<property name="visible">True</property>
<property name="title" translatable="yes">Virtual Machine Manager Preferences</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
<property name="resizable">True</property>
<property name="destroy_with_parent">False</property>
<property name="decorated">True</property>
<property name="skip_taskbar_hint">False</property>
<property name="skip_pager_hint">False</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
<property name="focus_on_map">True</property>
<property name="urgency_hint">False</property>
<property name="has_separator">False</property>
<signal name="delete_event" handler="on_vmm_preferences_delete_event" last_modification_time="Wed, 29 Mar 2006 10:12:05 GMT"/>
<child internal-child="vbox">
<widget class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child internal-child="action_area">
<widget class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="helpbutton1">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-help</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-11</property>
</widget>
</child>
<child>
<widget class="GtkButton" id="close">
<property name="visible">True</property>
<property name="can_default">True</property>
<property name="can_focus">True</property>
<property name="label">gtk-close</property>
<property name="use_stock">True</property>
<property name="relief">GTK_RELIEF_NORMAL</property>
<property name="focus_on_click">True</property>
<property name="response_id">-7</property>
<signal name="clicked" handler="on_close_clicked" last_modification_time="Wed, 29 Mar 2006 10:11:44 GMT"/>
</widget>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">GTK_PACK_END</property>
</packing>
</child>
<child>
<widget class="GtkVBox" id="vbox4">
<property name="visible">True</property>
<property name="homogeneous">False</property>
<property name="spacing">0</property>
<child>
<widget class="GtkFrame" id="frame1">
<property name="border_width">3</property>
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="label_yalign">0.5</property>
<property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
<child>
<widget class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xscale">1</property>
<property name="yscale">1</property>
<property name="top_padding">0</property>
<property name="bottom_padding">0</property>
<property name="left_padding">12</property>
<property name="right_padding">0</property>
<child>
<widget class="GtkTable" id="table3">
<property name="border_width">3</property>
<property name="visible">True</property>
<property name="n_rows">2</property>
<property name="n_columns">3</property>
<property name="homogeneous">False</property>
<property name="row_spacing">3</property>
<property name="column_spacing">3</property>
<child>
<widget class="GtkLabel" id="label36">
<property name="visible">True</property>
<property name="label" translatable="yes">Update status every</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label37">
<property name="visible">True</property>
<property name="label" translatable="yes">Maintain history of</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkSpinButton" id="stats-update-interval">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">0</property>
<property name="numeric">True</property>
<property name="update_policy">GTK_UPDATE_IF_VALID</property>
<property name="snap_to_ticks">False</property>
<property name="wrap">False</property>
<property name="adjustment">5 1 60 1 5 5</property>
<signal name="changed" handler="on_stats_update_interval_changed" last_modification_time="Wed, 29 Mar 2006 10:12:17 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label38">
<property name="visible">True</property>
<property name="label" translatable="yes">seconds</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">0</property>
<property name="bottom_attach">1</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkLabel" id="label39">
<property name="visible">True</property>
<property name="label" translatable="yes">samples</property>
<property name="use_underline">False</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
<widget class="GtkSpinButton" id="stats-history-length">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="climb_rate">1</property>
<property name="digits">0</property>
<property name="numeric">True</property>
<property name="update_policy">GTK_UPDATE_IF_VALID</property>
<property name="snap_to_ticks">False</property>
<property name="wrap">False</property>
<property name="adjustment">10 10 100 1 5 5</property>
<signal name="changed" handler="on_stats_history_length_changed" last_modification_time="Wed, 29 Mar 2006 10:12:22 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
</widget>
</child>
</widget>
</child>
<child>
<widget class="GtkLabel" id="label35">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;Status monitoring&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
<property name="wrap">False</property>
<property name="selectable">False</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
<property name="ypad">0</property>
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
<property name="width_chars">-1</property>
<property name="single_line_mode">False</property>
<property name="angle">0</property>
</widget>
<packing>
<property name="type">label_item</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
<packing>
<property name="padding">0</property>
<property name="expand">True</property>
<property name="fill">True</property>
</packing>
</child>
</widget>
</child>
</widget>
</glade-interface> </glade-interface>

View File

@ -1,15 +1,17 @@
#!/usr/bin/python #!/usr/bin/python
import gconf
import gtk import gtk
import gobject import gobject
import gtk.gdk import gtk.gdk
import gtk.glade import gtk.glade
from time import time
import re import re
import os import os
import os.path import os.path
import libvirt import libvirt
tickrate = 5000 gconf_dir = "/apps/gnome-virtual-manager"
# Ought not to hardcode stuff as being in /usr # Ought not to hardcode stuff as being in /usr
gladedir = "/usr/share/gnome-vm-manager" gladedir = "/usr/share/gnome-vm-manager"
@ -20,79 +22,167 @@ if os.path.exists("./gnome-vm-manager.glade"):
class vmmAbout: class vmmAbout:
def __init__(self): def __init__(self):
self.window = gtk.glade.XML(gladedir + "/gnome-vm-manager.glade", "vm-about") self.window = gtk.glade.XML(gladedir + "/gnome-vm-manager.glade", "vmm-about")
self.window.get_widget("vm-about").hide() self.window.get_widget("vmm-about").hide()
self.window.signal_autoconnect({
"on_vmm_about_delete_event": self.close,
})
def show(self): def show(self):
dialog = self.window.get_widget("vm-about") dialog = self.window.get_widget("vmm-about")
dialog.set_version("0.1") dialog.set_version("0.1")
dialog.show_all() dialog.show_all()
def close(self,ignore1=None,ignore2=None):
self.window.get_widget("vmm-about").hide()
return 1
class vmmDetails:
def __init__(self, vmm):
self.window = gtk.glade.XML(gladedir + "/gnome-vm-manager.glade", "vmm-details")
self.vmm = vmm
class vmmPreferences:
def __init__(self, conf):
self.window = gtk.glade.XML(gladedir + "/gnome-vm-manager.glade", "vmm-preferences")
self.conf = conf
self.window.get_widget("vmm-preferences").hide()
self.conf.on_stats_update_interval_changed(self.refresh_update_interval)
self.conf.on_stats_history_length_changed(self.refresh_history_length)
self.refresh_update_interval()
self.refresh_history_length()
self.window.signal_autoconnect({
"on_stats_update_interval_changed": self.change_update_interval,
"on_stats_history_length_changed": self.change_history_length,
"on_close_clicked": self.close,
"on_vmm_preferences_delete_event": self.close,
})
def close(self,ignore1=None,ignore2=None):
self.window.get_widget("vmm-preferences").hide()
return 1
def show(self):
self.window.get_widget("vmm-preferences").show_all()
def refresh_update_interval(self, ignore1=None,ignore2=None,ignore3=None,ignore4=None):
self.window.get_widget("stats-update-interval").set_value(self.conf.get_stats_update_interval())
def refresh_history_length(self, ignore1=None,ignore2=None,ignore3=None,ignore4=None):
self.window.get_widget("stats-history-length").set_value(self.conf.get_stats_history_length())
def change_update_interval(self, src):
self.conf.set_stats_update_interval(src.get_value_as_int())
def change_history_length(self, src):
self.conf.set_stats_history_length(src.get_value_as_int())
class vmmManager: class vmmManager:
def __init__(self): def __init__(self):
self.window = gtk.glade.XML(gladedir + "/gnome-vm-manager.glade", "vm-manager") self.window = gtk.glade.XML(gladedir + "/gnome-vm-manager.glade", "vmm-manager")
self.conf = vmmConfig()
self.vmm = libvirt.openReadOnly(None) self.vmm = libvirt.openReadOnly(None)
#self.vmm = libvirt.open(None) #self.vmm = libvirt.open(None)
self.stats = {} self.stats = vmmStats(self.vmm, self.conf)
self.record_stats()
self.populate_vms() self.populate_vms()
self.tickrate = 5000 self.about = None
self.about = None; self.preferences = None
self.timer = gobject.timeout_add(self.tickrate, self.refresh_stats) # Setup update timers
self.conf.on_stats_update_interval_changed(self.change_timer_interval)
self.schedule_timer()
self.conf.on_vmlist_status_visible_changed(self.toggle_status_visible_widget)
self.conf.on_vmlist_cpu_usage_visible_changed(self.toggle_cpu_usage_visible_widget)
self.conf.on_vmlist_memory_usage_visible_changed(self.toggle_memory_usage_visible_widget)
self.conf.on_vmlist_disk_usage_visible_changed(self.toggle_disk_usage_visible_widget)
self.conf.on_vmlist_network_traffic_visible_changed(self.toggle_network_traffic_visible_widget)
self.window.get_widget("menu_view_status").set_active(self.conf.is_vmlist_status_visible())
self.window.get_widget("menu_view_cpu_usage").set_active(self.conf.is_vmlist_cpu_usage_visible())
self.window.get_widget("menu_view_memory_usage").set_active(self.conf.is_vmlist_memory_usage_visible())
self.window.get_widget("menu_view_disk_usage").set_active(self.conf.is_vmlist_disk_usage_visible())
self.window.get_widget("menu_view_network_traffic").set_active(self.conf.is_vmlist_network_traffic_visible())
self.window.signal_autoconnect({ self.window.signal_autoconnect({
"on_menu_view_status_activate" : self.toggle_status_column, "on_menu_view_status_activate" : self.toggle_status_visible_conf,
"on_menu_view_cpu_usage_activate" : self.toggle_cpu_column, "on_menu_view_cpu_usage_activate" : self.toggle_cpu_usage_visible_conf,
"on_menu_view_memory_usage_activate" : self.toggle_memory_column, "on_menu_view_memory_usage_activate" : self.toggle_memory_usage_visible_conf,
"on_menu_view_disk_usage_activate" : self.toggle_disk_column, "on_menu_view_disk_usage_activate" : self.toggle_disk_usage_visible_conf,
"on_menu_view_network_traffic_activate" : self.toggle_network_column, "on_menu_view_network_traffic_activate" : self.toggle_network_traffic_visible_conf,
"on_vm_manager_delete_event": self.exit_app, "on_vm_manager_delete_event": self.exit_app,
"on_menu_file_quit_activate": self.exit_app, "on_menu_file_quit_activate": self.exit_app,
"on_vmm_close_clicked": self.exit_app, "on_vmm_close_clicked": self.exit_app,
"on_menu_edit_preferences_activate": self.show_preferences,
"on_menu_help_about_activate": self.show_about, "on_menu_help_about_activate": self.show_about,
}) })
self.vm_selected(None)
self.window.get_widget("vm-list").get_selection().connect("changed", self.vm_selected)
def exit_app(self, ignore=None,ignore2=None): def exit_app(self, ignore=None,ignore2=None):
gtk.main_quit() gtk.main_quit()
def schedule_timer(self):
interval = self.conf.get_stats_update_interval() * 1000
print "Scheduling at " + str(interval)
self.timer_started = time() * 1000
self.timer = gobject.timeout_add(interval, self.refresh_stats)
def change_timer_interval(self,ignore1,ignore2,ignore3,ignore4):
print "Removing timer"
gobject.source_remove(self.timer)
self.refresh_stats()
self.schedule_timer()
def vm_selected(self, selection):
if selection == None or selection.count_selected_rows() == 0:
self.window.get_widget("vm-delete").set_sensitive(False)
self.window.get_widget("vm-details").set_sensitive(False)
self.window.get_widget("vm-open").set_sensitive(False)
self.window.get_widget("menu_edit_delete").set_sensitive(False)
self.window.get_widget("menu_edit_details").set_sensitive(False)
else:
self.window.get_widget("vm-delete").set_sensitive(True)
self.window.get_widget("vm-details").set_sensitive(True)
self.window.get_widget("vm-open").set_sensitive(True)
self.window.get_widget("menu_edit_delete").set_sensitive(True)
self.window.get_widget("menu_edit_details").set_sensitive(True)
def show_about(self, ignore=None): def show_about(self, ignore=None):
if self.about == None: if self.about == None:
self.about = vmmAbout() self.about = vmmAbout()
self.about.show() self.about.show()
def show_preferences(self, ignore=None):
if self.preferences == None:
self.preferences = vmmPreferences(self.conf)
self.preferences.show()
def refresh_stats(self): def refresh_stats(self):
self.record_stats() self.stats.tick()
self.timer = gobject.timeout_add(self.tickrate, self.refresh_stats)
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
model = vmlist.get_model() model = vmlist.get_model()
print "Refresh " + str(model.iter_n_children(None))
for row in range(model.iter_n_children(None)): for row in range(model.iter_n_children(None)):
model.row_changed(str(row), model.iter_nth_child(None, row)) model.row_changed(str(row), model.iter_nth_child(None, row))
def record_stats(self): return 1
print "Record"
doms = self.vmm.listDomainsID()
if doms != None:
for id in self.vmm.listDomainsID():
vm = self.vmm.lookupByID(id)
info = vm.info()
name = vm.name()
if not(self.stats.has_key(name)):
self.stats[name] = []
if len(self.stats[name]) > 4:
self.stats[name] = (self.stats[name])[1:len(self.stats[name])]
self.stats[name].append(info)
# XXX why is max-mem wrong for Domain-0 when run as root ?!?!?!
#print info
def populate_vms(self): def populate_vms(self):
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
@ -105,7 +195,7 @@ class vmmManager:
cpuUsageCol = gtk.TreeViewColumn("CPU usage") cpuUsageCol = gtk.TreeViewColumn("CPU usage")
memoryUsageCol = gtk.TreeViewColumn("Memory usage") memoryUsageCol = gtk.TreeViewColumn("Memory usage")
diskUsageCol = gtk.TreeViewColumn("Disk usage") diskUsageCol = gtk.TreeViewColumn("Disk usage")
networkUsageCol = gtk.TreeViewColumn("Network traffic") networkTrafficCol = gtk.TreeViewColumn("Network traffic")
name_txt = gtk.CellRendererText() name_txt = gtk.CellRendererText()
nameCol.pack_start(name_txt, True) nameCol.pack_start(name_txt, True)
@ -116,27 +206,32 @@ class vmmManager:
vmlist.append_column(cpuUsageCol) vmlist.append_column(cpuUsageCol)
vmlist.append_column(memoryUsageCol) vmlist.append_column(memoryUsageCol)
vmlist.append_column(diskUsageCol) vmlist.append_column(diskUsageCol)
vmlist.append_column(networkUsageCol) vmlist.append_column(networkTrafficCol)
status_txt = gtk.CellRendererText() status_txt = gtk.CellRendererText()
statusCol.pack_start(status_txt, True) statusCol.pack_start(status_txt, True)
statusCol.set_cell_data_func(status_txt, self.status_text, None) statusCol.set_cell_data_func(status_txt, self.status_text, None)
statusCol.set_visible(self.conf.is_vmlist_status_visible())
cpuUsage_txt = gtk.CellRendererText() cpuUsage_txt = gtk.CellRendererText()
cpuUsageCol.pack_start(cpuUsage_txt, True) cpuUsageCol.pack_start(cpuUsage_txt, True)
cpuUsageCol.set_cell_data_func(cpuUsage_txt, self.cpu_usage_text, None) cpuUsageCol.set_cell_data_func(cpuUsage_txt, self.cpu_usage_text, None)
cpuUsageCol.set_visible(self.conf.is_vmlist_cpu_usage_visible())
memoryUsage_txt = gtk.CellRendererText() memoryUsage_txt = gtk.CellRendererText()
memoryUsageCol.pack_start(memoryUsage_txt, True) memoryUsageCol.pack_start(memoryUsage_txt, True)
memoryUsageCol.set_cell_data_func(memoryUsage_txt, self.memory_usage_text, None) memoryUsageCol.set_cell_data_func(memoryUsage_txt, self.memory_usage_text, None)
memoryUsageCol.set_visible(self.conf.is_vmlist_memory_usage_visible())
diskUsage_txt = gtk.CellRendererText() diskUsage_txt = gtk.CellRendererText()
diskUsageCol.pack_start(diskUsage_txt, True) diskUsageCol.pack_start(diskUsage_txt, True)
diskUsageCol.set_cell_data_func(diskUsage_txt, self.disk_usage_text, None) diskUsageCol.set_cell_data_func(diskUsage_txt, self.disk_usage_text, None)
diskUsageCol.set_visible(self.conf.is_vmlist_disk_usage_visible())
networkUsage_txt = gtk.CellRendererText() networkTraffic_txt = gtk.CellRendererText()
networkUsageCol.pack_start(networkUsage_txt, True) networkTrafficCol.pack_start(networkTraffic_txt, True)
networkUsageCol.set_cell_data_func(networkUsage_txt, self.network_usage_text, None) networkTrafficCol.set_cell_data_func(networkTraffic_txt, self.network_usage_text, None)
networkTrafficCol.set_visible(self.conf.is_vmlist_network_traffic_visible())
doms = self.vmm.listDomainsID() doms = self.vmm.listDomainsID()
if doms != None: if doms != None:
@ -144,79 +239,65 @@ class vmmManager:
vm = self.vmm.lookupByID(id) vm = self.vmm.lookupByID(id)
model.append([vm.name()]) model.append([vm.name()])
def toggle_status_column(self,menu): def toggle_status_visible_conf(self, menu):
self.conf.set_vmlist_status_visible(menu.get_active())
def toggle_status_visible_widget(self, ignore1, ignore2, ignore3, ignore4):
menu = self.window.get_widget("menu_view_status")
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
col = vmlist.get_column(1) col = vmlist.get_column(1)
col.set_visible(menu.get_active()) col.set_visible(self.conf.is_vmlist_status_visible())
def toggle_cpu_column(self,menu): def toggle_cpu_usage_visible_conf(self, menu):
self.conf.set_vmlist_cpu_usage_visible(menu.get_active())
def toggle_cpu_usage_visible_widget(self, ignore1, ignore2, ignore3, ignore4):
menu = self.window.get_widget("menu_view_cpu_usage")
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
col = vmlist.get_column(2) col = vmlist.get_column(2)
col.set_visible(menu.get_active()) col.set_visible(self.conf.is_vmlist_cpu_usage_visible())
def toggle_memory_column(self,menu): def toggle_memory_usage_visible_conf(self, menu):
self.conf.set_vmlist_memory_usage_visible(menu.get_active())
def toggle_memory_usage_visible_widget(self, ignore1, ignore2, ignore3, ignore4):
menu = self.window.get_widget("menu_view_memory_usage")
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
col = vmlist.get_column(3) col = vmlist.get_column(3)
col.set_visible(menu.get_active()) col.set_visible(self.conf.is_vmlist_memory_usage_visible())
def toggle_disk_column(self,menu): def toggle_disk_usage_visible_conf(self, menu):
self.conf.set_vmlist_disk_usage_visible(menu.get_active())
def toggle_disk_usage_visible_widget(self, ignore1, ignore2, ignore3, ignore4):
menu = self.window.get_widget("menu_view_disk_usage")
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
col = vmlist.get_column(4) col = vmlist.get_column(4)
col.set_visible(menu.get_active()) col.set_visible(self.conf.is_vmlist_disk_usage_visible())
def toggle_network_column(self,menu): def toggle_network_traffic_visible_conf(self, menu):
self.conf.set_vmlist_network_traffic_visible(menu.get_active())
def toggle_network_traffic_visible_widget(self, ignore1, ignore2, ignore3, ignore4):
menu = self.window.get_widget("menu_view_network_traffic")
vmlist = self.window.get_widget("vm-list") vmlist = self.window.get_widget("vm-list")
col = vmlist.get_column(5) col = vmlist.get_column(5)
col.set_visible(menu.get_active()) col.set_visible(self.conf.is_vmlist_network_traffic_visible())
def status_text(self, column, cell, model, iter, data): def status_text(self, column, cell, model, iter, data):
name = model.get_value(iter, 0) name = model.get_value(iter, 0)
statusRecord = self.stats[name] cell.set_property('text', self.stats.run_status(name))
info = statusRecord[len(statusRecord)-1]
if info[0] == libvirt.VIR_DOMAIN_NOSTATE:
cell.set_property('text', "Unknown")
elif info[0] == libvirt.VIR_DOMAIN_RUNNING:
cell.set_property('text', "Running")
elif info[0] == libvirt.VIR_DOMAIN_BLOCKED:
cell.set_property('text', "Blocked")
elif info[0] == libvirt.VIR_DOMAIN_PAUSED:
cell.set_property('text', "Paused")
elif info[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
cell.set_property('text', "Shutdown")
elif info[0] == libvirt.VIR_DOMAIN_SHUTOFF:
cell.set_property('text', "Shutoff")
elif info[0] == libvirt.VIR_DOMAIN_CRASHED:
cell.set_property('text', "Crashed")
def cpu_usage_text(self, column, cell, model, iter, data): def cpu_usage_text(self, column, cell, model, iter, data):
name = model.get_value(iter, 0) name = model.get_value(iter, 0)
statusRecord = self.stats[name] cell.set_property('text', "%2.2f %%" % self.stats.percent_cpu_time(name))
nSample = len(statusRecord)
if nSample < 2:
cell.set_property('text', "-")
else:
total = 0
for dom in self.stats.keys():
last = self.stats[dom][len(self.stats[dom])-2]
current = self.stats[dom][len(self.stats[dom])-1]
total += current[4] - last[4]
last = statusRecord[len(statusRecord)-2]
current = statusRecord[len(statusRecord)-1]
fraction = current[4] - last[4]
percentage = fraction * 100.0 / total
cell.set_property('text',"%2.2f %%" % percentage)
def memory_usage_text(self, column, cell, model, iter, data): def memory_usage_text(self, column, cell, model, iter, data):
name = model.get_value(iter, 0) name = model.get_value(iter, 0)
statusRecord = self.stats[name] current = self.stats.current_memory(name)
current = statusRecord[len(statusRecord)-1] maximum = self.stats.maximum_memory(name)
cell.set_property('text', "%s of %s" % (self.pretty_mem(current), self.pretty_mem(maximum)))
cell.set_property('text', "%s of %s" % (self.pretty_mem(current[2]), self.pretty_mem(current[1])))
#cell.set_property('text', self.pretty_mem(current[2])) #cell.set_property('text', self.pretty_mem(current[2]))
def pretty_mem(self, mem): def pretty_mem(self, mem):
@ -233,6 +314,193 @@ class vmmManager:
#cell.set_property('text', "100 bytes/sec") #cell.set_property('text', "100 bytes/sec")
cell.set_property('text', "-") cell.set_property('text', "-")
class vmmConfig:
def __init__(self):
self.conf = gconf.client_get_default()
self.conf.add_dir (gconf_dir,
gconf.CLIENT_PRELOAD_NONE)
def is_vmlist_status_visible(self):
return self.conf.get_bool(gconf_dir + "/vmlist-fields/status")
def is_vmlist_cpu_usage_visible(self):
return self.conf.get_bool(gconf_dir + "/vmlist-fields/cpu_usage")
def is_vmlist_memory_usage_visible(self):
return self.conf.get_bool(gconf_dir + "/vmlist-fields/memory_usage")
def is_vmlist_disk_usage_visible(self):
return self.conf.get_bool(gconf_dir + "/vmlist-fields/disk_usage")
def is_vmlist_network_traffic_visible(self):
return self.conf.get_bool(gconf_dir + "/vmlist-fields/network_traffic")
def set_vmlist_status_visible(self, state):
self.conf.set_bool(gconf_dir + "/vmlist-fields/status", state)
def set_vmlist_cpu_usage_visible(self, state):
self.conf.set_bool(gconf_dir + "/vmlist-fields/cpu_usage", state)
def set_vmlist_memory_usage_visible(self, state):
self.conf.set_bool(gconf_dir + "/vmlist-fields/memory_usage", state)
def set_vmlist_disk_usage_visible(self, state):
self.conf.set_bool(gconf_dir + "/vmlist-fields/disk_usage", state)
def set_vmlist_network_traffic_visible(self, state):
self.conf.set_bool(gconf_dir + "/vmlist-fields/network_traffic", state)
def on_vmlist_status_visible_changed(self, callback):
self.conf.notify_add(gconf_dir + "/vmlist-fields/status", callback)
def on_vmlist_cpu_usage_visible_changed(self, callback):
self.conf.notify_add(gconf_dir + "/vmlist-fields/cpu_usage", callback)
def on_vmlist_memory_usage_visible_changed(self, callback):
self.conf.notify_add(gconf_dir + "/vmlist-fields/memory_usage", callback)
def on_vmlist_disk_usage_visible_changed(self, callback):
self.conf.notify_add(gconf_dir + "/vmlist-fields/disk_usage", callback)
def on_vmlist_network_traffic_visible_changed(self, callback):
self.conf.notify_add(gconf_dir + "/vmlist-fields/network_traffic", callback)
def get_stats_update_interval(self):
interval = self.conf.get_int(gconf_dir + "/stats/update-interval")
if interval < 1:
return 1
return interval
def get_stats_history_length(self):
history = self.conf.get_int(gconf_dir + "/stats/history-length")
if history < 10:
return 10
return history
def set_stats_update_interval(self, interval):
self.conf.set_int(gconf_dir + "/stats/update-interval", interval)
def set_stats_history_length(self, length):
self.conf.set_int(gconf_dir + "/stats/history-length", length)
def on_stats_update_interval_changed(self, callback):
self.conf.notify_add(gconf_dir + "/stats/update-interval", callback)
def on_stats_history_length_changed(self, callback):
self.conf.notify_add(gconf_dir + "/stats/history-length", callback)
class vmmStats:
def __init__(self, vmm, conf):
self.vmm = vmm
self.vms = {}
self.conf = conf
self.callbacks = { "notify_added": [], "notify_removed": [] }
self.tick()
def connect_to_signal(self, name, callback):
if not(self.callbacks.has_key(name)):
raise "unknown signal " + name + "requested"
self.callbacks[name].append(callback)
def notify_added(self, name):
for cb in self.callbacks["notify_added"]:
cb(name)
def notify_removed(self, name):
for cb in self.callbacks["notify_added"]:
cb(name)
def tick(self):
doms = self.vmm.listDomainsID()
newVms = {}
if doms != None:
for id in self.vmm.listDomainsID():
vm = self.vmm.lookupByID(id)
newVms[vm.name()] = vm
for name in self.vms.keys():
if not(newVms.has_key(name)):
del self.vms[name]
self.notify_removed(name)
for name in newVms.keys():
if not(self.vms.has_key(name)):
self.vms[name] = { "handle": newVms[name],
"stats": [] }
self.notify_added(name)
now = time()
totalCpuTime = 0
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]
prevCpuTime = 0
prevTimestamp = 0
if len(self.vms[name]["stats"]) > 0:
prevTimestamp = self.vms[name]["stats"][0]["timestamp"]
prevCpuTime = self.vms[name]["stats"][0]["absCpuTime"]
print str(now-prevTimestamp)
print str(info[4]-prevCpuTime)
print str((now - prevTimestamp)*1000 * 1000)
print
pcentCpuTime = (info[4]-prevCpuTime) * 100 / ((now - prevTimestamp)*1000 * 1000*1000)
newStats = [{ "timestamp": now,
"status": info[0],
"absCpuTime": info[4],
"relCpuTime": (info[4]-prevCpuTime),
"pcentCpuTime": pcentCpuTime,
"currMem": info[2],
"maxMem": info[1] }]
totalCpuTime = totalCpuTime + newStats[0]["relCpuTime"]
newStats.append(self.vms[name]["stats"])
self.vms[name]["stats"] = newStats
def current_memory(self, name):
return self.vms[name]["stats"][0]["currMem"]
def maximum_memory(self, name):
return self.vms[name]["stats"][0]["maxMem"]
def percent_cpu_time(self, name):
return self.vms[name]["stats"][0]["pcentCpuTime"]
def run_status(self, name):
status = self.vms[name]["stats"][0]["status"]
if status == libvirt.VIR_DOMAIN_NOSTATE:
return "Idle"
elif status == libvirt.VIR_DOMAIN_RUNNING:
return "Running"
elif status == libvirt.VIR_DOMAIN_BLOCKED:
return "Blocked"
elif status == libvirt.VIR_DOMAIN_PAUSED:
return "Paused"
elif status == libvirt.VIR_DOMAIN_SHUTDOWN:
return "Shutdown"
elif status == libvirt.VIR_DOMAIN_SHUTOFF:
return "Shutoff"
elif status == libvirt.VIR_DOMAIN_CRASHED:
return "Crashed"
else:
raise "Unknown status code"
# Run me! # Run me!
def main(): def main():
window = vmmManager() window = vmmManager()