virt-manager/virtManager/host.py

659 lines
23 KiB
Python
Raw Normal View History

# Copyright (C) 2007, 2013-2014 Red Hat, Inc.
# Copyright (C) 2007 Daniel P. Berrange <berrange@redhat.com>
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import logging
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 08:24:56 -05:00
from gi.repository import Gtk
from virtinst import NodeDevice
from virtinst import util
from . import uiutil
from .asyncjob import vmmAsyncJob
from .baseclass import vmmGObjectUI
from .createnet import vmmCreateNetwork
from .engine import vmmEngine
from .graphwidgets import Sparkline
from .storagelist import vmmStorageList
EDIT_NET_IDS = (
EDIT_NET_NAME,
2013-09-29 11:28:01 -05:00
EDIT_NET_AUTOSTART,
EDIT_NET_QOS,
) = list(range(3))
2013-09-29 11:28:01 -05:00
ICON_RUNNING = "state_running"
ICON_SHUTOFF = "state_shutoff"
2010-12-08 16:26:19 -06:00
class vmmHost(vmmGObjectUI):
@classmethod
def show_instance(cls, parentobj, conn):
try:
# Maintain one dialog per connection
uri = conn.get_uri()
if cls._instances is None:
cls._instances = {}
if uri not in cls._instances:
cls._instances[uri] = vmmHost(conn)
cls._instances[uri].show()
except Exception as e:
if not parentobj:
raise
parentobj.err.show_err(
_("Error launching host dialog: %s") % str(e))
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 08:24:56 -05:00
def __init__(self, conn):
vmmGObjectUI.__init__(self, "host.ui", "vmm-host")
self.conn = conn
self._orig_title = self.topwin.get_title()
# Set default window size
w, h = self.conn.get_details_window_size()
if w <= 0:
w = 800
if h <= 0:
h = 600
self.topwin.set_default_size(w, h)
self._window_size = None
self._addnet = None
self._active_edits = set()
2013-09-29 11:14:00 -05:00
self._cpu_usage_graph = None
self._memory_usage_graph = None
self._init_conn_state()
self._storagelist = None
self._init_storage_state()
self._init_net_state()
self.builder.connect_signals({
"on_menu_file_view_manager_activate": self._view_manager_cb,
"on_menu_file_quit_activate": self._exit_app_cb,
"on_menu_file_close_activate": self.close,
"on_vmm_host_delete_event": self.close,
"on_vmm_host_configure_event": self._window_resized_cb,
"on_host_page_switch": self._page_changed_cb,
"on_net_add_clicked": self._add_network_cb,
"on_net_delete_clicked": self._delete_network_cb,
"on_net_stop_clicked": self._stop_network_cb,
"on_net_start_clicked": self._start_network_cb,
"on_net_apply_clicked": (lambda *x: self._net_apply()),
"on_net_list_changed": self._net_selected_cb,
"on_net_autostart_toggled": (lambda *x:
self._enable_net_apply(EDIT_NET_AUTOSTART)),
2013-09-29 11:14:00 -05:00
"on_net_name_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_NAME)),
"on_overview_name_changed": self._overview_name_changed_cb,
"on_config_autoconnect_toggled": self._autoconnect_toggled_cb,
"on_qos_inbound_average_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_QOS)),
"on_qos_inbound_peak_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_QOS)),
"on_qos_inbound_burst_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_QOS)),
"on_qos_outbound_average_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_QOS)),
"on_qos_outbound_peak_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_QOS)),
"on_qos_outbound_burst_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_QOS)),
"on_net_qos_inbound_enable_toggled": self._change_qos_cb,
"on_net_qos_outbound_enable_toggled": self._change_qos_cb,
2012-11-08 07:15:02 -06:00
})
self._populate_networks()
self.conn.connect("net-added", self._conn_nets_changed_cb)
self.conn.connect("net-removed", self._conn_nets_changed_cb)
self.conn.connect("state-changed", self._conn_state_changed_cb)
self.conn.connect("resources-sampled", self._conn_resources_sampled_cb)
self._refresh_resources()
self._refresh_conn()
self.widget("config-autoconnect").set_active(
self.conn.get_autoconnect())
self._cleanup_on_conn_removed()
#######################
# Standard UI methods #
#######################
def show(self):
logging.debug("Showing host details: %s", self.conn)
vis = self.is_visible()
self.topwin.present()
if vis:
return
vmmEngine.get_instance().increment_window_counter()
def close(self, src=None, event=None):
dummy = src
dummy = event
logging.debug("Closing host window for %s", self.conn)
if not self.is_visible():
return
self._confirm_changes()
self.topwin.hide()
vmmEngine.get_instance().decrement_window_counter()
return 1
def _cleanup(self):
if self._window_size:
self.conn.set_details_window_size(*self._window_size)
self.conn = None
self._storagelist.cleanup()
self._storagelist = None
if self._addnet:
self._addnet.cleanup()
self._addnet = None
self._cpu_usage_graph.destroy()
self._cpu_usage_graph = None
self._memory_usage_graph.destroy()
self._memory_usage_graph = None
###########
# UI init #
###########
def _init_net_state(self):
self.widget("network-pages").set_show_tabs(False)
# [ unique, label, icon name, icon size, is_active ]
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 08:24:56 -05:00
netListModel = Gtk.ListStore(str, str, str, int, bool)
self.widget("net-list").set_model(netListModel)
sel = self.widget("net-list").get_selection()
sel.set_select_function((lambda *x: self._confirm_changes()), None)
netCol = Gtk.TreeViewColumn(_("Networks"))
netCol.set_spacing(6)
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 08:24:56 -05:00
net_txt = Gtk.CellRendererText()
net_img = Gtk.CellRendererPixbuf()
netCol.pack_start(net_img, False)
netCol.pack_start(net_txt, True)
netCol.add_attribute(net_txt, 'text', 1)
netCol.add_attribute(net_txt, 'sensitive', 4)
netCol.add_attribute(net_img, 'icon-name', 2)
netCol.add_attribute(net_img, 'stock-size', 3)
self.widget("net-list").append_column(netCol)
Convert to use GTK3 and GObject Introspection bindings Switch over to use GObject introspection bindings for all python modules related to GObject/GTK3/etc. It is not possible to mix and match old pyggtk/pygobject manual bindings with new introspection based bindings so it must be all changed in one go. Imports like import gtk Change to from gi.repository import Gtk The vmmGObject class is changed to always inherit from GObject.GObject There is no compelling reason to avoid a GObject dep for the virt-manager TUI & it horribly messed up the code. Signal declarations are changed from vmmChooseCD.signal_new(vmmChooseCD, "cdrom-chosen", [object, str]) To __gsignals__ = { "cdrom-chosen": (GObject.SignalFlags.RUN_FIRST, None, [object, str]) } which is required by new GObject bindings Most of the rest of the change is simply dealing with renamed constants / classes. Alot of legacy compat code was removed - ie helpers which check to see if certain GTK2 methods are available are no longer required since we're mandating GTK3 only. The event loop is replaced with LibvirtGLib's event loop. Still todo - Rip out all DBus stuff & make vmmEngine class inherit GtkApplication which provides unique support & DBus method handling - Switch to use LibvirtGConfig & LibvirtGObject for libvirt interaction - Possibly switch to Python 3 too ? - Figure out why GNOME keyring is missing Introspection support My suggestion is that the standalone GIT repo for virt-install only live on as a support branch for legacy platforms. A stable-0.9 branch of virt-manager can be kept for legacy PyGtk2 based virt-manager releases. The virt-manager master branch should exclusively use GObject inspection and ideally Python3 and contain both the virt-manager and virt-install codebases in one since they are intimately related to each other & using separate GIT repos has needlessly complicated life for everyone. crobinso: Some locking fixes Misc cleanups and dropping now-useless code Fix dbus usage Fix graph cell renderer regression Fix a couple tooltip issues
2012-05-14 08:24:56 -05:00
netListModel.set_sort_column_id(1, Gtk.SortType.ASCENDING)
# Virtual Function list
# [vf-name]
vf_list = self.widget("vf-list")
vf_list_model = Gtk.ListStore(str)
vf_list.set_model(vf_list_model)
vf_list.set_headers_visible(False)
vfTextCol = Gtk.TreeViewColumn()
vf_txt = Gtk.CellRendererText()
vfTextCol.pack_start(vf_txt, True)
vfTextCol.add_attribute(vf_txt, 'text', 0)
vf_list.append_column(vfTextCol)
def _init_storage_state(self):
self._storagelist = vmmStorageList(self.conn, self.builder, self.topwin)
self.widget("storage-align").add(self._storagelist.top_box)
def _init_conn_state(self):
uri = self.conn.get_uri()
auto = self.conn.get_autoconnect()
self.widget("overview-uri").set_text(uri)
self.widget("config-autoconnect").set_active(auto)
self._cpu_usage_graph = Sparkline()
self._cpu_usage_graph.show()
self.widget("performance-cpu-align").add(self._cpu_usage_graph)
self._memory_usage_graph = Sparkline()
self._memory_usage_graph.show()
self.widget("performance-memory-align").add(self._memory_usage_graph)
######################
# UI conn populating #
######################
def _refresh_resources(self):
vm_memory = util.pretty_mem(self.conn.stats_memory())
host_memory = util.pretty_mem(self.conn.host_memory_size())
cpu_vector = self.conn.host_cpu_time_vector()
memory_vector = self.conn.stats_memory_vector()
cpu_vector.reverse()
memory_vector.reverse()
self.widget("performance-cpu").set_text("%d %%" %
self.conn.host_cpu_time_percentage())
self.widget("performance-memory").set_text(
_("%(currentmem)s of %(maxmem)s") %
{'currentmem': vm_memory, 'maxmem': host_memory})
self._cpu_usage_graph.set_property("data_array", cpu_vector)
self._memory_usage_graph.set_property("data_array", memory_vector)
def _refresh_conn(self):
2014-09-11 17:16:21 -05:00
conn_active = self.conn.is_active()
self.topwin.set_title(
self.conn.get_pretty_desc() + " " + self._orig_title)
if not self.widget("overview-name").has_focus():
self.widget("overview-name").set_text(self.conn.get_pretty_desc())
self.widget("net-add").set_sensitive(conn_active and
self.conn.is_network_capable())
if conn_active and not self.conn.is_network_capable():
self._set_net_error_page(
_("Libvirt connection does not support virtual network "
"management."))
if conn_active:
uiutil.set_list_selection_by_number(self.widget("net-list"), 0)
return
self._set_net_error_page(_("Connection not active."))
self._populate_networks()
2013-09-29 11:14:00 -05:00
self._storagelist.close()
if self._addnet:
self._addnet.close()
2013-09-29 11:14:00 -05:00
#####################
# UI net populating #
#####################
def _current_network(self):
connkey = uiutil.get_list_selection(self.widget("net-list"))
return connkey and self.conn.get_net(connkey)
def _set_net_error_page(self, msg):
self.widget("network-pages").set_current_page(1)
self.widget("network-error-label").set_text(msg)
def _refresh_current_network(self):
net = self._current_network()
if not net:
self._set_net_error_page(_("No virtual network selected."))
return
self.widget("network-pages").set_current_page(0)
try:
self._populate_net_state(net)
except Exception as e:
logging.exception(e)
self._set_net_error_page(_("Error selecting network: %s") % e)
finally:
self._disable_net_apply()
def _populate_networks(self):
net_list = self.widget("net-list")
curnet = self._current_network()
model = net_list.get_model()
# Prevent events while the model is modified
net_list.set_model(None)
try:
net_list.get_selection().unselect_all()
model.clear()
for net in self.conn.list_nets():
net.disconnect_by_obj(self)
net.connect("state-changed", self._net_state_changed_cb)
model.append([net.get_connkey(), net.get_name(), "network-idle",
Gtk.IconSize.LARGE_TOOLBAR,
bool(net.is_active())])
2013-09-29 11:14:00 -05:00
finally:
net_list.set_model(model)
uiutil.set_list_selection(net_list,
curnet and curnet.get_connkey() or None)
def _populate_net_ipv4_state(self, net):
(netstr,
(dhcpstart, dhcpend),
(routeaddr, routevia)) = net.get_ipv4_network()
self.widget("net-ipv4-expander").set_visible(bool(netstr))
if not netstr:
return
forward = net.get_ipv4_forward_mode()
self.widget("net-ipv4-forwarding-icon").set_from_stock(
forward and Gtk.STOCK_CONNECT or Gtk.STOCK_DISCONNECT,
Gtk.IconSize.MENU)
self.widget("net-ipv4-forwarding").set_text(net.pretty_forward_mode())
dhcpstr = _("Disabled")
if dhcpstart:
dhcpstr = dhcpstart + " - " + dhcpend
self.widget("net-ipv4-dhcp-range").set_text(dhcpstr)
self.widget("net-ipv4-network").set_text(netstr)
uiutil.set_grid_row_visible(
self.widget("net-ipv4-route"), bool(routevia))
if routevia:
routevia = routeaddr + ", gateway=" + routevia
self.widget("net-ipv4-route").set_text(routevia or "")
def _populate_net_ipv6_state(self, net):
(netstr,
(dhcpstart, dhcpend),
(routeaddr, routevia)) = net.get_ipv6_network()
self.widget("net-ipv6-expander").set_visible(bool(netstr))
self.widget("net-ipv6-forwarding-icon").set_from_stock(
netstr and Gtk.STOCK_CONNECT or Gtk.STOCK_DISCONNECT,
Gtk.IconSize.MENU)
if netstr:
prettymode = _("Routed network")
elif net.get_ipv6_enabled():
prettymode = _("Isolated network, internal routing only")
else:
prettymode = _("Isolated network, routing disabled")
self.widget("net-ipv6-forwarding").set_text(prettymode)
dhcpstr = _("Disabled")
if dhcpstart:
dhcpstr = dhcpstart + " - " + dhcpend
self.widget("net-ipv6-dhcp-range").set_text(dhcpstr)
self.widget("net-ipv6-network").set_text(netstr or "")
uiutil.set_grid_row_visible(
self.widget("net-ipv6-route"), bool(routevia))
if routevia:
routevia = routeaddr + ", gateway=" + routevia
self.widget("net-ipv6-route").set_text(routevia or "")
def _update_qos_widgets(self):
enabled = self.widget("net-qos-inbound-enable").get_active()
self.widget("net-qos-inbound-grid").set_visible(enabled)
enabled = self.widget("net-qos-outbound-enable").get_active()
self.widget("net-qos-outbound-grid").set_visible(enabled)
def _populate_qos_state(self, net):
qos = net.get_qos()
self.widget("net-qos-inbound-enable").set_active(qos.is_inbound())
self.widget("net-qos-outbound-enable").set_active(qos.is_outbound())
self._update_qos_widgets()
self.widget("qos-inbound-average").set_text(qos.inbound_average or "")
self.widget("qos-inbound-peak").set_text(qos.inbound_peak or "")
self.widget("qos-inbound-burst").set_text(qos.inbound_burst or "")
self.widget("qos-outbound-average").set_text(qos.outbound_average or "")
self.widget("qos-outbound-peak").set_text(qos.outbound_peak or "")
self.widget("qos-outbound-burst").set_text(qos.outbound_burst or "")
def _populate_sriov_state(self, net):
(is_vf_pool, pf_name, vfs) = net.get_sriov_vf_networks()
self.widget("net-sriov-expander").set_visible(is_vf_pool)
if not pf_name:
self.widget("pf-name").set_text("N/A")
return
self.widget("pf-name").set_text(pf_name)
vf_list_model = self.widget("vf-list").get_model()
vf_list_model.clear()
for vf in vfs:
addrStr = "%x:%x:%x.%x" % (vf.domain, vf.bus, vf.slot, vf.function)
pcidev = NodeDevice.lookupNodedevFromString(self.conn.get_backend(),
addrStr)
vf_name = None
netdevs = self.conn.filter_nodedevs("net")
for netdev in netdevs:
logging.debug(netdev.xmlobj.parent)
if pcidev.name == netdev.xmlobj.parent:
vf_name = netdev.xmlobj.interface
break
vf_list_model.append([vf_name or addrStr])
def _populate_net_state(self, net):
active = net.is_active()
self.widget("net-details").set_sensitive(True)
2013-09-29 11:14:00 -05:00
self.widget("net-name").set_text(net.get_name())
self.widget("net-name").set_editable(not active)
self.widget("net-device").set_text(net.get_bridge_device() or "")
self.widget("net-name-domain").set_text(net.get_name_domain() or "")
uiutil.set_grid_row_visible(self.widget("net-name-domain"),
bool(net.get_name_domain()))
state = active and _("Active") or _("Inactive")
icon = (active and ICON_RUNNING or ICON_SHUTOFF)
self.widget("net-state").set_text(state)
self.widget("net-state-icon").set_from_icon_name(icon,
2014-01-12 13:36:03 -06:00
Gtk.IconSize.BUTTON)
self.widget("net-start").set_sensitive(not active)
self.widget("net-stop").set_sensitive(active)
self.widget("net-delete").set_sensitive(not active)
autostart = net.get_autostart()
self.widget("net-autostart").set_active(autostart)
self.widget("net-autostart").set_label(_("On Boot"))
self._populate_net_ipv4_state(net)
self._populate_net_ipv6_state(net)
self._populate_qos_state(net)
self._populate_sriov_state(net)
#############################
# Network lifecycle actions #
#############################
def _delete_network_cb(self, src):
net = self._current_network()
if net is None:
return
result = self.err.yes_no(_("Are you sure you want to permanently "
"delete the network %s?") % net.get_name())
if not result:
return
logging.debug("Deleting network '%s'", net.get_name())
vmmAsyncJob.simple_async_noshow(net.delete, [], self,
_("Error deleting network '%s'") % net.get_name())
def _start_network_cb(self, src):
net = self._current_network()
if net is None:
return
logging.debug("Starting network '%s'", net.get_name())
vmmAsyncJob.simple_async_noshow(net.start, [], self,
_("Error starting network '%s'") % net.get_name())
def _stop_network_cb(self, src):
net = self._current_network()
if net is None:
return
logging.debug("Stopping network '%s'", net.get_name())
self.widget("vf-list").get_model().clear()
vmmAsyncJob.simple_async_noshow(net.stop, [], self,
_("Error stopping network '%s'") % net.get_name())
def _add_network_cb(self, src):
logging.debug("Launching 'Add Network'")
try:
if self._addnet is None:
self._addnet = vmmCreateNetwork(self.conn)
self._addnet.show(self.topwin)
except Exception as e:
self.err.show_err(_("Error launching network wizard: %s") % str(e))
############################
# Net apply/config actions #
############################
def _net_apply(self):
net = self._current_network()
if net is None:
return
logging.debug("Applying changes for network '%s'", net.get_name())
try:
if EDIT_NET_AUTOSTART in self._active_edits:
auto = self.widget("net-autostart").get_active()
net.set_autostart(auto)
if EDIT_NET_NAME in self._active_edits:
net.define_name(self.widget("net-name").get_text())
self.idle_add(self._populate_networks)
if EDIT_NET_QOS in self._active_edits:
in_qos = self.widget("net-qos-inbound-enable").get_active()
out_qos = self.widget("net-qos-outbound-enable").get_active()
def get_value(name, enabled):
if not enabled:
return None
return self.widget(name).get_text() or None
args = {}
args['inbound_average'] = get_value("qos-inbound-average", in_qos)
args['inbound_peak'] = get_value("qos-inbound-peak", in_qos)
args['inbound_burst'] = get_value("qos-inbound-burst", in_qos)
args['outbound_average'] = get_value("qos-outbound-average", out_qos)
args['outbound_peak'] = get_value("qos-outbound-peak", out_qos)
args['outbound_burst'] = get_value("qos-outbound-burst", out_qos)
if net.set_qos(**args):
self.err.show_err(
_("Network could not be updated"),
text2=_("This change will take effect when the "
"network is restarted"),
buttons=Gtk.ButtonsType.OK,
dialog_type=Gtk.MessageType.INFO)
except Exception as e:
self.err.show_err(_("Error changing network settings: %s") % str(e))
return
finally:
self._disable_net_apply()
def _disable_net_apply(self):
self._active_edits = set()
self.widget("net-apply").set_sensitive(False)
def _enable_net_apply(self, edittype):
self.widget("net-apply").set_sensitive(True)
self._active_edits.add(edittype)
def _confirm_changes(self):
if not self._active_edits:
return True
if self.err.chkbox_helper(
self.config.get_confirm_unapplied,
self.config.set_confirm_unapplied,
text1=(_("There are unapplied changes. "
"Would you like to apply them now?")),
chktext=_("Don't warn me again."),
default=False):
if all([edit in EDIT_NET_IDS for edit in self._active_edits]):
self._net_apply()
self._active_edits = set()
return True
################
# UI listeners #
################
def _view_manager_cb(self, src):
from .manager import vmmManager
vmmManager.get_instance(self).show()
def _exit_app_cb(self, src):
vmmEngine.get_instance().exit_app()
def _window_resized_cb(self, src, event):
if not self.is_visible():
return
self._window_size = self.topwin.get_size()
def _overview_name_changed_cb(self, src):
src = self.widget("overview-name")
self.conn.set_config_pretty_name(src.get_text())
def _autoconnect_toggled_cb(self, src):
self.conn.set_autoconnect(src.get_active())
def _change_qos_cb(self, src):
self._enable_net_apply(EDIT_NET_QOS)
self._update_qos_widgets()
def _page_changed_cb(self, src, child, pagenum):
self._confirm_changes()
if pagenum == 1:
self._populate_networks()
self.conn.schedule_priority_tick(pollnet=True)
elif pagenum == 2:
self._storagelist.refresh_page()
def _conn_state_changed_cb(self, conn):
self._refresh_conn()
def _conn_resources_sampled_cb(self, conn):
self._refresh_resources()
def _conn_nets_changed_cb(self, src, connkey):
self._populate_networks()
def _net_state_changed_cb(self, net):
# Update net state inline in the tree model
for row in self.widget("net-list").get_model():
if row[0] == net.get_connkey():
row[4] = net.is_active()
# If refreshed network is the current net, refresh the UI
curnet = self._current_network()
if curnet and curnet.get_connkey() == net.get_connkey():
self._refresh_current_network()
def _net_selected_cb(self, selection):
self._refresh_current_network()