host: separate out hostnets.ui and hostnets.py

Helps organize things by limiting the files to a single class of
operations, and follows the storagelist.py pattern
This commit is contained in:
Cole Robinson 2019-04-14 15:34:40 -04:00
parent 891968085c
commit 86a13699ce
4 changed files with 1576 additions and 1494 deletions

1058
ui/host.ui

File diff suppressed because it is too large Load Diff

1065
ui/hostnets.ui Normal file

File diff suppressed because it is too large Load Diff

View File

@ -6,29 +6,14 @@
import logging
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 .hostnets import vmmHostNets
from .storagelist import vmmStorageList
EDIT_NET_IDS = (
EDIT_NET_NAME,
EDIT_NET_AUTOSTART,
EDIT_NET_QOS,
) = list(range(3))
ICON_RUNNING = "state_running"
ICON_SHUTOFF = "state_shutoff"
class vmmHost(vmmGObjectUI):
@classmethod
@ -62,16 +47,14 @@ class vmmHost(vmmGObjectUI):
self.topwin.set_default_size(w, h)
self._window_size = None
self._addnet = None
self._active_edits = set()
self._cpu_usage_graph = None
self._memory_usage_graph = None
self._init_conn_state()
self._storagelist = None
self._init_storage_state()
self._hostnets = None
self._init_net_state()
self.builder.connect_signals({
@ -82,47 +65,15 @@ class vmmHost(vmmGObjectUI):
"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)),
"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,
})
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._refresh_conn_state()
self.widget("config-autoconnect").set_active(
self.conn.get_autoconnect())
@ -165,9 +116,8 @@ class vmmHost(vmmGObjectUI):
self._storagelist.cleanup()
self._storagelist = None
if self._addnet:
self._addnet.cleanup()
self._addnet = None
self._hostnets.cleanup()
self._hostnets = None
self._cpu_usage_graph.destroy()
self._cpu_usage_graph = None
@ -181,40 +131,8 @@ class vmmHost(vmmGObjectUI):
###########
def _init_net_state(self):
self.widget("network-pages").set_show_tabs(False)
# [ unique, label, icon name, icon size, is_active ]
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)
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)
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)
self._hostnets = vmmHostNets(self.conn, self.builder, self.topwin)
self.widget("net-align").add(self._hostnets.top_box)
def _init_storage_state(self):
self._storagelist = vmmStorageList(self.conn, self.builder, self.topwin)
@ -258,7 +176,7 @@ class vmmHost(vmmGObjectUI):
self._cpu_usage_graph.set_property("data_array", cpu_vector)
self._memory_usage_graph.set_property("data_array", memory_vector)
def _refresh_conn(self):
def _refresh_conn_state(self):
conn_active = self.conn.is_active()
self.topwin.set_title(
@ -266,336 +184,12 @@ class vmmHost(vmmGObjectUI):
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()
self._hostnets.close()
self._storagelist.close()
if self._addnet:
self._addnet.close()
#####################
# 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())])
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)
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,
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
@ -622,37 +216,15 @@ class vmmHost(vmmGObjectUI):
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)
self._hostnets.refresh_page()
elif pagenum == 2:
self._storagelist.refresh_page()
def _conn_state_changed_cb(self, conn):
self._refresh_conn()
self._refresh_conn_state()
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()

495
virtManager/hostnets.py Normal file
View File

@ -0,0 +1,495 @@
# 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
from gi.repository import Gtk
from virtinst import NodeDevice
from . import uiutil
from .asyncjob import vmmAsyncJob
from .baseclass import vmmGObjectUI
from .createnet import vmmCreateNetwork
EDIT_NET_IDS = (
EDIT_NET_NAME,
EDIT_NET_AUTOSTART,
EDIT_NET_QOS,
) = list(range(3))
ICON_RUNNING = "state_running"
ICON_SHUTOFF = "state_shutoff"
class vmmHostNets(vmmGObjectUI):
def __init__(self, conn, builder, topwin):
vmmGObjectUI.__init__(self, "hostnets.ui",
None, builder=builder, topwin=topwin)
self.conn = conn
self._addnet = None
self._active_edits = set()
self.top_box = self.widget("top-box")
self.builder.connect_signals({
"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)),
"on_net_name_changed": (lambda *x:
self._enable_net_apply(EDIT_NET_NAME)),
"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,
})
self._init_ui()
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)
#######################
# Standard UI methods #
#######################
def _cleanup(self):
self.conn = None
if self._addnet:
self._addnet.cleanup()
self._addnet = None
def close(self, ignore1=None, ignore2=None):
if self._addnet:
self._addnet.close()
###########
# UI init #
###########
def _init_ui(self):
self.widget("network-pages").set_show_tabs(False)
# [ unique, label, icon name, icon size, is_active ]
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)
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)
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)
##############
# Public API #
##############
def refresh_page(self):
self._populate_networks()
self.conn.schedule_priority_tick(pollnet=True)
#################
# UI populating #
#################
def _refresh_conn_state(self):
conn_active = self.conn.is_active()
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_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_error_page(_("Connection not active."))
self._populate_networks()
def _current_network(self):
connkey = uiutil.get_list_selection(self.widget("net-list"))
return connkey and self.conn.get_net(connkey)
def _set_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_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_error_page(_("Error selecting network: %s") % e)
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())])
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)
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,
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):
self._net_apply()
self._active_edits = set()
return True
################
# UI listeners #
################
def _conn_state_changed_cb(self, conn):
self._refresh_conn_state()
def _conn_nets_changed_cb(self, src, connkey):
self._populate_networks()
def _change_qos_cb(self, src):
self._enable_net_apply(EDIT_NET_QOS)
self._update_qos_widgets()
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()