2014-07-23 08:48:17 -05:00
|
|
|
# Copyright (C) 2007, 2013-2014 Red Hat, Inc.
|
2007-03-27 18:52:00 -05:00
|
|
|
# Copyright (C) 2007 Daniel P. Berrange <berrange@redhat.com>
|
|
|
|
#
|
2018-04-04 08:35:41 -05:00
|
|
|
# This work is licensed under the GNU GPLv2 or later.
|
2018-03-20 14:00:02 -05:00
|
|
|
# See the COPYING file in the top-level directory.
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2010-02-25 16:42:00 -06:00
|
|
|
import logging
|
2008-08-15 10:07:45 -05:00
|
|
|
|
2012-05-14 08:24:56 -05:00
|
|
|
from gi.repository import Gtk
|
2011-04-18 11:39:53 -05:00
|
|
|
|
2017-09-22 06:39:10 -05:00
|
|
|
from virtinst import NodeDevice
|
2015-05-04 15:33:56 -05:00
|
|
|
from virtinst import util
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2014-09-12 15:10:45 -05:00
|
|
|
from . import uiutil
|
|
|
|
from .asyncjob import vmmAsyncJob
|
2015-04-08 17:29:48 -05:00
|
|
|
from .baseclass import vmmGObjectUI
|
2014-09-12 15:10:45 -05:00
|
|
|
from .createnet import vmmCreateNetwork
|
2018-03-14 17:58:22 -05:00
|
|
|
from .engine import vmmEngine
|
2014-09-12 15:10:45 -05:00
|
|
|
from .graphwidgets import Sparkline
|
2015-04-08 17:29:48 -05:00
|
|
|
from .storagelist import vmmStorageList
|
2007-03-29 20:23:17 -05:00
|
|
|
|
2014-07-23 08:48:17 -05:00
|
|
|
EDIT_NET_IDS = (
|
|
|
|
EDIT_NET_NAME,
|
2013-09-29 11:28:01 -05:00
|
|
|
EDIT_NET_AUTOSTART,
|
2014-06-25 05:36:46 -05:00
|
|
|
EDIT_NET_QOS,
|
2017-10-11 06:35:57 -05:00
|
|
|
) = list(range(3))
|
2013-09-29 11:28:01 -05:00
|
|
|
|
2013-04-13 13:34:52 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
ICON_RUNNING = "state_running"
|
|
|
|
ICON_SHUTOFF = "state_shutoff"
|
|
|
|
|
|
|
|
|
2010-12-08 16:26:19 -06:00
|
|
|
class vmmHost(vmmGObjectUI):
|
2018-03-15 04:53:58 -05:00
|
|
|
@classmethod
|
|
|
|
def show_instance(cls, parentobj, conn):
|
|
|
|
try:
|
|
|
|
# Maintain one dialog per connection
|
|
|
|
uri = conn.get_uri()
|
2018-03-17 18:42:19 -05:00
|
|
|
if cls._instances is None:
|
|
|
|
cls._instances = {}
|
2018-03-15 04:53:58 -05:00
|
|
|
if uri not in cls._instances:
|
2018-03-17 15:08:20 -05:00
|
|
|
cls._instances[uri] = vmmHost(conn)
|
2018-03-15 04:53:58 -05:00
|
|
|
cls._instances[uri].show()
|
|
|
|
except Exception as e:
|
2018-03-16 17:58:11 -05:00
|
|
|
if not parentobj:
|
|
|
|
raise
|
2018-03-15 04:53:58 -05:00
|
|
|
parentobj.err.show_err(
|
|
|
|
_("Error launching host dialog: %s") % str(e))
|
2012-05-14 08:24:56 -05:00
|
|
|
|
2011-04-13 09:47:31 -05:00
|
|
|
def __init__(self, conn):
|
2013-09-22 15:10:16 -05:00
|
|
|
vmmGObjectUI.__init__(self, "host.ui", "vmm-host")
|
2007-03-27 18:52:00 -05:00
|
|
|
self.conn = conn
|
|
|
|
|
2015-04-11 12:39:25 -05:00
|
|
|
self._orig_title = self.topwin.get_title()
|
2008-08-15 10:07:45 -05:00
|
|
|
|
2019-04-13 13:52:17 -05:00
|
|
|
# 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
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._addnet = None
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._active_edits = set()
|
2013-09-29 11:14:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._cpu_usage_graph = None
|
|
|
|
self._memory_usage_graph = None
|
|
|
|
self._init_conn_state()
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._storagelist = None
|
|
|
|
self._init_storage_state()
|
|
|
|
self._init_net_state()
|
2009-11-19 16:29:20 -06:00
|
|
|
|
2013-02-16 12:31:46 -06:00
|
|
|
self.builder.connect_signals({
|
2019-04-13 11:03:42 -05:00
|
|
|
"on_menu_file_view_manager_activate": self._view_manager_cb,
|
|
|
|
"on_menu_file_quit_activate": self._exit_app_cb,
|
2007-03-27 18:52:00 -05:00
|
|
|
"on_menu_file_close_activate": self.close,
|
|
|
|
"on_vmm_host_delete_event": self.close,
|
2019-04-13 13:52:17 -05:00
|
|
|
"on_vmm_host_configure_event": self._window_resized_cb,
|
2019-04-13 11:03:42 -05:00
|
|
|
"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:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_NAME)),
|
2010-02-08 16:13:36 -06:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
"on_overview_name_changed": self._overview_name_changed_cb,
|
|
|
|
"on_config_autoconnect_toggled": self._autoconnect_toggled_cb,
|
2014-06-25 05:36:46 -05:00
|
|
|
|
|
|
|
"on_qos_inbound_average_changed": (lambda *x:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_QOS)),
|
2014-06-25 05:36:46 -05:00
|
|
|
"on_qos_inbound_peak_changed": (lambda *x:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_QOS)),
|
2014-06-25 05:36:46 -05:00
|
|
|
"on_qos_inbound_burst_changed": (lambda *x:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_QOS)),
|
2014-06-25 05:36:46 -05:00
|
|
|
"on_qos_outbound_average_changed": (lambda *x:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_QOS)),
|
2014-06-25 05:36:46 -05:00
|
|
|
"on_qos_outbound_peak_changed": (lambda *x:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_QOS)),
|
2014-06-25 05:36:46 -05:00
|
|
|
"on_qos_outbound_burst_changed": (lambda *x:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._enable_net_apply(EDIT_NET_QOS)),
|
2014-06-25 05:36:46 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
"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
|
|
|
})
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._populate_networks()
|
2013-09-23 11:37:03 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self.conn.connect("net-added", self._conn_nets_changed_cb)
|
|
|
|
self.conn.connect("net-removed", self._conn_nets_changed_cb)
|
2013-09-23 11:37:03 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self.conn.connect("state-changed", self._conn_state_changed_cb)
|
|
|
|
self.conn.connect("resources-sampled", self._conn_resources_sampled_cb)
|
2015-04-08 17:29:48 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._refresh_resources()
|
|
|
|
self._refresh_conn()
|
2015-04-08 17:29:48 -05:00
|
|
|
self.widget("config-autoconnect").set_active(
|
|
|
|
self.conn.get_autoconnect())
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2018-03-15 06:43:56 -05:00
|
|
|
self._cleanup_on_conn_removed()
|
|
|
|
|
2009-03-08 14:34:15 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
#######################
|
|
|
|
# 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):
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("network-pages").set_show_tabs(False)
|
2010-02-25 16:31:27 -06:00
|
|
|
|
2009-11-19 16:29:20 -06:00
|
|
|
# [ unique, label, icon name, icon size, is_active ]
|
2012-05-14 08:24:56 -05:00
|
|
|
netListModel = Gtk.ListStore(str, str, str, int, bool)
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("net-list").set_model(netListModel)
|
2009-11-17 14:44:27 -06:00
|
|
|
|
2014-07-23 08:48:17 -05:00
|
|
|
sel = self.widget("net-list").get_selection()
|
2019-04-13 11:03:42 -05:00
|
|
|
sel.set_select_function((lambda *x: self._confirm_changes()), None)
|
2014-07-23 08:48:17 -05:00
|
|
|
|
2016-02-05 09:18:16 -06:00
|
|
|
netCol = Gtk.TreeViewColumn(_("Networks"))
|
2009-11-17 14:44:27 -06:00
|
|
|
netCol.set_spacing(6)
|
2012-05-14 08:24:56 -05:00
|
|
|
net_txt = Gtk.CellRendererText()
|
|
|
|
net_img = Gtk.CellRendererPixbuf()
|
2009-11-17 14:44:27 -06:00
|
|
|
netCol.pack_start(net_img, False)
|
|
|
|
netCol.pack_start(net_txt, True)
|
|
|
|
netCol.add_attribute(net_txt, 'text', 1)
|
2009-11-19 16:29:20 -06:00
|
|
|
netCol.add_attribute(net_txt, 'sensitive', 4)
|
2009-11-17 14:44:27 -06:00
|
|
|
netCol.add_attribute(net_img, 'icon-name', 2)
|
|
|
|
netCol.add_attribute(net_img, 'stock-size', 3)
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("net-list").append_column(netCol)
|
2012-05-14 08:24:56 -05:00
|
|
|
netListModel.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
2009-11-17 14:44:27 -06:00
|
|
|
|
2017-09-22 06:39:10 -05:00
|
|
|
# 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)
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _init_storage_state(self):
|
|
|
|
self._storagelist = vmmStorageList(self.conn, self.builder, self.topwin)
|
|
|
|
self.widget("storage-align").add(self._storagelist.top_box)
|
2017-09-22 06:39:10 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _init_conn_state(self):
|
2009-11-17 14:44:27 -06:00
|
|
|
uri = self.conn.get_uri()
|
|
|
|
auto = self.conn.get_autoconnect()
|
|
|
|
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("overview-uri").set_text(uri)
|
|
|
|
self.widget("config-autoconnect").set_active(auto)
|
2009-11-17 14:44:27 -06:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._cpu_usage_graph = Sparkline()
|
|
|
|
self._cpu_usage_graph.show()
|
|
|
|
self.widget("performance-cpu-align").add(self._cpu_usage_graph)
|
2011-04-13 08:27:02 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._memory_usage_graph = Sparkline()
|
|
|
|
self._memory_usage_graph.show()
|
|
|
|
self.widget("performance-memory-align").add(self._memory_usage_graph)
|
2015-04-08 17:29:48 -05:00
|
|
|
|
2009-11-17 14:18:38 -06:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
######################
|
|
|
|
# UI conn populating #
|
|
|
|
######################
|
2013-07-07 10:06:15 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _refresh_resources(self):
|
2015-05-04 15:33:56 -05:00
|
|
|
vm_memory = util.pretty_mem(self.conn.stats_memory())
|
|
|
|
host_memory = util.pretty_mem(self.conn.host_memory_size())
|
|
|
|
|
2011-07-11 20:22:50 -05:00
|
|
|
cpu_vector = self.conn.host_cpu_time_vector()
|
|
|
|
memory_vector = self.conn.stats_memory_vector()
|
2007-03-27 18:52:00 -05:00
|
|
|
cpu_vector.reverse()
|
|
|
|
memory_vector.reverse()
|
2011-07-11 20:22:50 -05:00
|
|
|
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("performance-cpu").set_text("%d %%" %
|
2011-07-11 20:22:50 -05:00
|
|
|
self.conn.host_cpu_time_percentage())
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("performance-memory").set_text(
|
2011-07-11 20:22:50 -05:00
|
|
|
_("%(currentmem)s of %(maxmem)s") %
|
|
|
|
{'currentmem': vm_memory, 'maxmem': host_memory})
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._cpu_usage_graph.set_property("data_array", cpu_vector)
|
|
|
|
self._memory_usage_graph.set_property("data_array", memory_vector)
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _refresh_conn(self):
|
2014-09-11 17:16:21 -05:00
|
|
|
conn_active = self.conn.is_active()
|
2015-04-11 12:39:25 -05:00
|
|
|
|
|
|
|
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())
|
|
|
|
|
2013-06-30 11:42:49 -05:00
|
|
|
self.widget("net-add").set_sensitive(conn_active and
|
|
|
|
self.conn.is_network_capable())
|
|
|
|
|
2015-04-10 08:31:13 -05:00
|
|
|
if conn_active and not self.conn.is_network_capable():
|
2019-04-13 11:03:42 -05:00
|
|
|
self._set_net_error_page(
|
2010-03-20 17:42:32 -05:00
|
|
|
_("Libvirt connection does not support virtual network "
|
|
|
|
"management."))
|
|
|
|
|
2015-04-09 14:07:16 -05:00
|
|
|
if conn_active:
|
2015-05-19 17:13:33 -05:00
|
|
|
uiutil.set_list_selection_by_number(self.widget("net-list"), 0)
|
2015-04-09 14:07:16 -05:00
|
|
|
return
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._set_net_error_page(_("Connection not active."))
|
2014-06-25 05:36:46 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._populate_networks()
|
2013-09-29 11:14:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._storagelist.close()
|
|
|
|
if self._addnet:
|
|
|
|
self._addnet.close()
|
2008-08-26 10:17:31 -05:00
|
|
|
|
2013-09-29 11:14:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
#####################
|
|
|
|
# UI net populating #
|
|
|
|
#####################
|
2008-08-26 10:17:31 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _current_network(self):
|
2015-05-19 16:17:53 -05:00
|
|
|
connkey = uiutil.get_list_selection(self.widget("net-list"))
|
2015-05-07 10:23:00 -05:00
|
|
|
return connkey and self.conn.get_net(connkey)
|
2007-04-03 13:01:45 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _set_net_error_page(self, msg):
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("network-pages").set_current_page(1)
|
|
|
|
self.widget("network-error-label").set_text(msg)
|
2010-02-25 16:31:27 -06:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _refresh_current_network(self):
|
|
|
|
net = self._current_network()
|
|
|
|
if not net:
|
|
|
|
self._set_net_error_page(_("No virtual network selected."))
|
2008-08-26 09:55:03 -05:00
|
|
|
return
|
2009-03-08 14:34:15 -05:00
|
|
|
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("network-pages").set_current_page(0)
|
2014-06-02 16:17:47 -05:00
|
|
|
|
2013-03-29 13:38:28 -05:00
|
|
|
try:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._populate_net_state(net)
|
2017-05-05 11:47:21 -05:00
|
|
|
except Exception as e:
|
2010-02-25 16:42:00 -06:00
|
|
|
logging.exception(e)
|
2019-04-13 11:03:42 -05:00
|
|
|
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:
|
2019-04-13 11:03:42 -05:00
|
|
|
net_list.set_model(model)
|
|
|
|
|
|
|
|
uiutil.set_list_selection(net_list,
|
|
|
|
curnet and curnet.get_connkey() or None)
|
2010-02-25 18:42:08 -06:00
|
|
|
|
2013-09-20 19:40:07 -05:00
|
|
|
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)
|
|
|
|
|
2014-01-26 17:15:50 -06:00
|
|
|
uiutil.set_grid_row_visible(
|
2013-09-20 19:40:07 -05:00
|
|
|
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 "")
|
|
|
|
|
2014-01-26 17:15:50 -06:00
|
|
|
uiutil.set_grid_row_visible(
|
2013-09-20 19:40:07 -05:00
|
|
|
self.widget("net-ipv6-route"), bool(routevia))
|
|
|
|
if routevia:
|
|
|
|
routevia = routeaddr + ", gateway=" + routevia
|
|
|
|
self.widget("net-ipv6-route").set_text(routevia or "")
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _update_qos_widgets(self):
|
2014-06-25 05:36:46 -05:00
|
|
|
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())
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._update_qos_widgets()
|
2014-06-25 05:36:46 -05:00
|
|
|
|
|
|
|
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 "")
|
|
|
|
|
2017-09-22 06:39:10 -05:00
|
|
|
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])
|
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _populate_net_state(self, net):
|
2008-08-26 09:55:03 -05:00
|
|
|
active = net.is_active()
|
|
|
|
|
2011-07-14 12:13:13 -05:00
|
|
|
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)
|
2013-09-20 19:40:07 -05:00
|
|
|
self.widget("net-device").set_text(net.get_bridge_device() or "")
|
|
|
|
self.widget("net-name-domain").set_text(net.get_name_domain() or "")
|
2014-01-26 17:15:50 -06:00
|
|
|
uiutil.set_grid_row_visible(self.widget("net-name-domain"),
|
2013-09-20 19:40:07 -05:00
|
|
|
bool(net.get_name_domain()))
|
2008-08-26 09:55:03 -05:00
|
|
|
|
2009-11-16 06:14:49 -06:00
|
|
|
state = active and _("Active") or _("Inactive")
|
2019-04-13 11:03:42 -05:00
|
|
|
icon = (active and ICON_RUNNING or ICON_SHUTOFF)
|
2011-07-14 12:13:13 -05:00
|
|
|
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)
|
2008-08-26 09:55:03 -05:00
|
|
|
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("net-start").set_sensitive(not active)
|
|
|
|
self.widget("net-stop").set_sensitive(active)
|
|
|
|
self.widget("net-delete").set_sensitive(not active)
|
2008-08-26 09:55:03 -05:00
|
|
|
|
|
|
|
autostart = net.get_autostart()
|
2011-07-14 12:13:13 -05:00
|
|
|
self.widget("net-autostart").set_active(autostart)
|
2017-03-21 10:19:05 -05:00
|
|
|
self.widget("net-autostart").set_label(_("On Boot"))
|
2008-08-26 09:55:03 -05:00
|
|
|
|
2013-09-20 19:40:07 -05:00
|
|
|
self._populate_net_ipv4_state(net)
|
|
|
|
self._populate_net_ipv6_state(net)
|
2014-06-25 05:36:46 -05:00
|
|
|
self._populate_qos_state(net)
|
2017-09-22 06:39:10 -05:00
|
|
|
self._populate_sriov_state(net)
|
2013-03-29 13:38:28 -05:00
|
|
|
|
2008-08-26 10:17:31 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
#############################
|
|
|
|
# Network lifecycle actions #
|
|
|
|
#############################
|
2007-03-29 20:23:17 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _delete_network_cb(self, src):
|
|
|
|
net = self._current_network()
|
|
|
|
if net is None:
|
|
|
|
return
|
2013-09-30 17:46:54 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
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'")
|
2015-04-11 10:40:47 -05:00
|
|
|
try:
|
2019-04-13 11:03:42 -05:00
|
|
|
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
|
2015-04-11 10:40:47 -05:00
|
|
|
finally:
|
2019-04-13 11:03:42 -05:00
|
|
|
self._disable_net_apply()
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _disable_net_apply(self):
|
|
|
|
self._active_edits = set()
|
|
|
|
self.widget("net-apply").set_sensitive(False)
|
2009-03-08 14:34:15 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _enable_net_apply(self, edittype):
|
|
|
|
self.widget("net-apply").set_sensitive(True)
|
|
|
|
self._active_edits.add(edittype)
|
2007-03-27 18:52:00 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
def _confirm_changes(self):
|
|
|
|
if not self._active_edits:
|
2014-07-23 08:48:17 -05:00
|
|
|
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):
|
2014-09-20 16:30:36 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
if all([edit in EDIT_NET_IDS for edit in self._active_edits]):
|
|
|
|
self._net_apply()
|
2014-07-23 08:48:17 -05:00
|
|
|
|
2019-04-13 11:03:42 -05:00
|
|
|
self._active_edits = set()
|
2014-07-23 08:48:17 -05:00
|
|
|
return True
|
2019-04-13 11:03:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
################
|
|
|
|
# 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()
|