# # Copyright (C) 2007, 2013-2014 Red Hat, Inc. # Copyright (C) 2007 Daniel P. Berrange # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA. # import logging from gi.repository import GObject from gi.repository import Gtk from virtinst import Interface from virtinst import util from . import uiutil from .asyncjob import vmmAsyncJob from .baseclass import vmmGObjectUI from .createnet import vmmCreateNetwork from .createinterface import vmmCreateInterface from .graphwidgets import Sparkline from .storagelist import vmmStorageList INTERFACE_PAGE_INFO = 0 INTERFACE_PAGE_ERROR = 1 EDIT_NET_IDS = ( EDIT_NET_NAME, EDIT_NET_AUTOSTART, EDIT_NET_QOS, ) = range(3) EDIT_INTERFACE_IDS = ( EDIT_INTERFACE_STARTMODE, ) = range(200, 201) class vmmHost(vmmGObjectUI): __gsignals__ = { "action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []), "action-view-manager": (GObject.SignalFlags.RUN_FIRST, None, []), "action-restore-domain": (GObject.SignalFlags.RUN_FIRST, None, [str]), "host-closed": (GObject.SignalFlags.RUN_FIRST, None, []), "host-opened": (GObject.SignalFlags.RUN_FIRST, None, []), } def __init__(self, conn): vmmGObjectUI.__init__(self, "host.ui", "vmm-host") self.conn = conn self._orig_title = self.topwin.get_title() self.ICON_RUNNING = "state_running" self.ICON_SHUTOFF = "state_shutoff" self.addnet = None self.addinterface = None self.active_edits = [] 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.init_interface_state() self.builder.connect_signals({ "on_menu_file_view_manager_activate" : self.view_manager, "on_menu_file_quit_activate" : self.exit_app, "on_menu_file_close_activate": self.close, "on_vmm_host_delete_event": self.close, "on_host_page_switch": self.page_changed, "on_menu_restore_saved_activate": self.restore_domain, "on_net_add_clicked": self.add_network, "on_net_delete_clicked": self.delete_network, "on_net_stop_clicked": self.stop_network, "on_net_start_clicked": self.start_network, "on_net_apply_clicked": (lambda *x: self.net_apply()), "on_net_list_changed": self.net_selected, "on_net_autostart_toggled": self.net_autostart_changed, "on_net_name_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_NAME)), "on_interface_add_clicked" : self.add_interface, "on_interface_start_clicked" : self.start_interface, "on_interface_stop_clicked" : self.stop_interface, "on_interface_delete_clicked" : self.delete_interface, "on_interface_startmode_changed": self.interface_startmode_changed, "on_interface_apply_clicked" : (lambda *x: self.interface_apply()), "on_interface_list_changed": self.interface_selected, "on_overview_name_changed": self._overview_name_changed, "on_config_autoconnect_toggled": self.toggle_autoconnect, "on_qos_inbound_average_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_QOS)), "on_qos_inbound_peak_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_QOS)), "on_qos_inbound_burst_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_QOS)), "on_qos_outbound_average_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_QOS)), "on_qos_outbound_peak_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_QOS)), "on_qos_outbound_burst_changed": (lambda *x: self.enable_net_apply(x, EDIT_NET_QOS)), "on_net_qos_inbound_enable_toggled": self.change_qos_in_enable, "on_net_qos_outbound_enable_toggled": self.change_qos_out_enable, }) self.populate_networks() self.populate_interfaces() self.conn.connect("net-added", self.populate_networks) self.conn.connect("net-removed", self.populate_networks) self.conn.connect("interface-added", self.populate_interfaces) self.conn.connect("interface-removed", self.populate_interfaces) self.conn.connect("state-changed", self.conn_state_changed) self.conn.connect("resources-sampled", self.refresh_resources) self.refresh_resources() self.conn_state_changed() self.widget("config-autoconnect").set_active( self.conn.get_autoconnect()) 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) 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_interface_state(self): self.widget("interface-pages").set_show_tabs(False) # [ unique, label, icon name, icon size, is_active ] interfaceListModel = Gtk.ListStore(str, str, str, int, bool) self.widget("interface-list").set_model(interfaceListModel) sel = self.widget("interface-list").get_selection() sel.set_select_function((lambda *x: self.confirm_changes()), None) interfaceCol = Gtk.TreeViewColumn("Interfaces") interfaceCol.set_spacing(6) interface_txt = Gtk.CellRendererText() interface_img = Gtk.CellRendererPixbuf() interfaceCol.pack_start(interface_img, False) interfaceCol.pack_start(interface_txt, True) interfaceCol.add_attribute(interface_txt, 'text', 1) interfaceCol.add_attribute(interface_txt, 'sensitive', 4) interfaceCol.add_attribute(interface_img, 'icon-name', 2) interfaceCol.add_attribute(interface_img, 'stock-size', 3) self.widget("interface-list").append_column(interfaceCol) interfaceListModel.set_sort_column_id(1, Gtk.SortType.ASCENDING) # Startmode combo vmmCreateInterface.build_interface_startmode_combo( self.widget("interface-startmode")) # [ name, type ] childListModel = Gtk.ListStore(str, str) childList = self.widget("interface-child-list") childList.set_model(childListModel) childNameCol = Gtk.TreeViewColumn("Name") child_txt1 = Gtk.CellRendererText() childNameCol.pack_start(child_txt1, True) childNameCol.add_attribute(child_txt1, 'text', 0) childNameCol.set_sort_column_id(0) childList.append_column(childNameCol) childTypeCol = Gtk.TreeViewColumn("Interface Type") child_txt2 = Gtk.CellRendererText() childTypeCol.pack_start(child_txt2, True) childTypeCol.add_attribute(child_txt2, 'text', 1) childTypeCol.set_sort_column_id(1) childList.append_column(childTypeCol) childListModel.set_sort_column_id(0, Gtk.SortType.ASCENDING) 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) def show(self): logging.debug("Showing host details: %s", self.conn) vis = self.is_visible() self.topwin.present() if vis: return self.emit("host-opened") def is_visible(self): return self.topwin.get_visible() def close(self, ignore1=None, ignore2=None): logging.debug("Closing host details: %s", self.conn) if not self.is_visible(): return self.confirm_changes() self.topwin.hide() self.emit("host-closed") return 1 def _cleanup(self): self.conn = None self.storagelist.cleanup() self.storagelist = None if self.addnet: self.addnet.cleanup() self.addnet = None if self.addinterface: self.addinterface.cleanup() self.addinterface = None self.cpu_usage_graph.destroy() self.cpu_usage_graph = None self.memory_usage_graph.destroy() self.memory_usage_graph = None def view_manager(self, src_ignore): self.emit("action-view-manager") def restore_domain(self, src_ignore): self.emit("action-restore-domain", self.conn.get_uri()) def exit_app(self, src_ignore): self.emit("action-exit-app") def page_changed(self, src, child, pagenum): ignore = src ignore = child self.confirm_changes() if pagenum == 1: self.populate_networks() self.conn.schedule_priority_tick(pollnet=True) elif pagenum == 2: self.storagelist.refresh_page() elif pagenum == 3: self.populate_interfaces() self.conn.schedule_priority_tick(polliface=True) def refresh_resources(self, ignore=None): 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 conn_state_changed(self, ignore1=None): 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("menu_file_restore_saved").set_sensitive(conn_active) self.widget("net-add").set_sensitive(conn_active and self.conn.is_network_capable()) self.widget("interface-add").set_sensitive(conn_active and self.conn.is_interface_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 and not self.conn.is_interface_capable(): self.set_interface_error_page( _("Libvirt connection does not support interface management.")) if conn_active: uiutil.set_list_selection_by_number(self.widget("net-list"), 0) uiutil.set_list_selection_by_number(self.widget("interface-list"), 0) return self.set_net_error_page(_("Connection not active.")) self.set_interface_error_page(_("Connection not active.")) self.populate_networks() self.populate_interfaces() self.storagelist.close() if self.addinterface: self.addinterface.close() if self.addnet: self.addnet.close() def _overview_name_changed(self, src): src = self.widget("overview-name") self.conn.set_config_pretty_name(src.get_text()) def toggle_autoconnect(self, src): self.conn.set_autoconnect(src.get_active()) ############################# # Virtual Network functions # ############################# def delete_network(self, src_ignore): 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(self, src_ignore): 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(self, src_ignore): net = self.current_network() if net is None: return logging.debug("Stopping network '%s'", net.get_name()) vmmAsyncJob.simple_async_noshow(net.stop, [], self, _("Error stopping network '%s'") % net.get_name()) def add_network(self, src_ignore): logging.debug("Launching 'Add Network'") try: if self.addnet is None: self.addnet = vmmCreateNetwork(self.conn) self.addnet.show(self.topwin) except Exception, e: self.err.show_err(_("Error launching network wizard: %s") % str(e)) 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, e: self.err.show_err(_("Error changing network settings: %s") % str(e)) return finally: self.disable_net_apply() def disable_net_apply(self): for i in EDIT_NET_IDS: if i in self.active_edits: self.active_edits.remove(i) self.widget("net-apply").set_sensitive(False) def disable_interface_apply(self): for i in EDIT_INTERFACE_IDS: if i in self.active_edits: self.active_edits.remove(i) self.widget("interface-apply").set_sensitive(False) def enable_net_apply(self, *arglist): edittype = arglist[-1] self.widget("net-apply").set_sensitive(True) if edittype not in self.active_edits: self.active_edits.append(edittype) def enable_interface_apply(self, *arglist): edittype = arglist[-1] self.widget("interface-apply").set_sensitive(True) if edittype not in self.active_edits: self.active_edits.append(edittype) def net_autostart_changed(self, src_ignore): auto = self.widget("net-autostart").get_active() self.widget("net-autostart").set_label(auto and _("On Boot") or _("Never")) self.enable_net_apply(EDIT_NET_AUTOSTART) def current_network(self): connkey = uiutil.get_list_selection(self.widget("net-list")) return connkey and self.conn.get_net(connkey) def refresh_network(self, net): connkey = net.get_connkey() uilist = self.widget("net-list") sel = uilist.get_selection() model, treeiter = sel.get_selected() for row in uilist.get_model(): if row[0] == connkey: row[4] = net.is_active() if treeiter is not None: if model[treeiter][0] == connkey: self.net_selected(sel) def set_net_error_page(self, msg): self.reset_net_state() self.widget("network-pages").set_current_page(1) self.widget("network-error-label").set_text(msg) def net_selected(self, src): model, treeiter = src.get_selected() if treeiter is None: self.set_net_error_page(_("No virtual network selected.")) return self.widget("network-pages").set_current_page(0) connkey = model[treeiter][0] try: net = self.conn.get_net(connkey) self.populate_net_state(net) except Exception, e: logging.exception(e) self.set_net_error_page(_("Error selecting network: %s") % e) finally: self.disable_net_apply() 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 change_qos_in_enable(self, ignore): self.enable_net_apply(EDIT_NET_QOS) self.update_qos_widgets() def change_qos_out_enable(self, ignore): self.enable_net_apply(EDIT_NET_QOS) self.update_qos_widgets() 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_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 self.ICON_RUNNING or self.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() autolabel = autostart and _("On Boot") or _("Never") self.widget("net-autostart").set_active(autostart) self.widget("net-autostart").set_label(autolabel) self._populate_net_ipv4_state(net) self._populate_net_ipv6_state(net) self._populate_qos_state(net) def reset_net_state(self): self.widget("net-details").set_sensitive(False) self.widget("net-name").set_text("") self.widget("net-device").set_text("") self.widget("net-state").set_text(_("Inactive")) self.widget("net-state-icon").set_from_icon_name(self.ICON_SHUTOFF, Gtk.IconSize.BUTTON) self.widget("net-start").set_sensitive(False) self.widget("net-stop").set_sensitive(False) self.widget("net-delete").set_sensitive(False) self.widget("net-autostart").set_label(_("Never")) self.widget("net-autostart").set_active(False) self.widget("net-ipv4-network").set_text("") self.widget("net-ipv4-dhcp-range").set_text("") self.widget("net-ipv4-route").set_text("") self.widget("net-ipv4-forwarding-icon").set_from_stock( Gtk.STOCK_DISCONNECT, Gtk.IconSize.MENU) self.widget("net-ipv4-forwarding").set_text( _("Isolated network")) self.widget("net-ipv6-network").set_text("") self.widget("net-ipv6-dhcp-range").set_text("") self.widget("net-ipv6-route").set_text("") self.widget("net-ipv6-forwarding").set_text( _("Isolated network")) self.disable_net_apply() def populate_networks(self, src=None, connkey=None): ignore = src ignore = connkey 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(): try: net.disconnect_by_func(self.refresh_network) except: pass net.connect("state-changed", self.refresh_network) 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) ############################# # Interface manager methods # ############################# def stop_interface(self, src_ignore): interface = self.current_interface() if interface is None: return if not self.err.chkbox_helper(self.config.get_confirm_interface, self.config.set_confirm_interface, text1=_("Are you sure you want to stop the interface " "'%s'?" % interface.get_name())): return logging.debug("Stopping interface '%s'", interface.get_name()) vmmAsyncJob.simple_async_noshow(interface.stop, [], self, _("Error stopping interface '%s'") % interface.get_name()) def start_interface(self, src_ignore): interface = self.current_interface() if interface is None: return if not self.err.chkbox_helper(self.config.get_confirm_interface, self.config.set_confirm_interface, text1=_("Are you sure you want to start the interface " "'%s'?" % interface.get_name())): return logging.debug("Starting interface '%s'", interface.get_name()) vmmAsyncJob.simple_async_noshow(interface.start, [], self, _("Error starting interface '%s'") % interface.get_name()) def delete_interface(self, src_ignore): interface = self.current_interface() if interface is None: return result = self.err.yes_no(_("Are you sure you want to permanently " "delete the interface %s?") % interface.get_name()) if not result: return logging.debug("Deleting interface '%s'", interface.get_name()) vmmAsyncJob.simple_async_noshow(interface.delete, [], self, _("Error deleting interface '%s'") % interface.get_name()) def add_interface(self, src_ignore): logging.debug("Launching 'Add Interface' wizard") try: if self.addinterface is None: self.addinterface = vmmCreateInterface(self.conn) self.addinterface.show(self.topwin) except Exception, e: self.err.show_err(_("Error launching interface wizard: %s") % str(e)) def refresh_current_interface(self, ignore1=None): cp = self.current_interface() if cp is None: return self.refresh_interface(cp) def current_interface(self): connkey = uiutil.get_list_selection(self.widget("interface-list")) return connkey and self.conn.get_interface(connkey) def interface_apply(self): interface = self.current_interface() if interface is None: return newmode = uiutil.get_list_selection( self.widget("interface-startmode")) logging.debug("Applying changes for interface '%s'", interface.get_name()) try: interface.set_startmode(newmode) except Exception, e: self.err.show_err(_("Error setting interface startmode: %s") % str(e)) return self.disable_interface_apply() def interface_startmode_changed(self, src_ignore): self.enable_interface_apply(EDIT_INTERFACE_STARTMODE) def set_interface_error_page(self, msg): self.reset_interface_state() self.widget("interface-pages").set_current_page(INTERFACE_PAGE_ERROR) self.widget("interface-error-label").set_text(msg) def interface_selected(self, src): model, treeiter = src.get_selected() if treeiter is None: self.set_interface_error_page(_("No interface selected.")) return self.widget("interface-pages").set_current_page(INTERFACE_PAGE_INFO) connkey = model[treeiter][0] try: self.populate_interface_state(connkey) except Exception, e: logging.exception(e) self.set_interface_error_page(_("Error selecting interface: %s") % e) self.disable_interface_apply() def populate_interface_state(self, connkey): interface = self.conn.get_interface(connkey) name = interface.get_name() children = interface.get_slaves() itype = interface.get_type() mac = interface.get_mac() active = interface.is_active() startmode = interface.get_startmode() ipv4 = interface.get_ipv4() ipv6 = interface.get_ipv6() self.widget("interface-details").set_sensitive(True) self.widget("interface-name").set_markup( "%s %s:" % (interface.get_pretty_type(), interface.get_name())) self.widget("interface-mac").set_text(mac or _("Unknown")) self.widget("interface-state-icon").set_from_icon_name( ((active and self.ICON_RUNNING) or self.ICON_SHUTOFF), Gtk.IconSize.BUTTON) self.widget("interface-state").set_text( (active and _("Active")) or _("Inactive")) # Set start mode start_list = self.widget("interface-startmode") start_model = start_list.get_model() start_label = self.widget("interface-startmode-label") start_list.hide() start_label.show() start_label.set_text(startmode) idx = 0 for row in start_model: if row[0] == startmode: start_list.set_active(idx) start_list.show() start_label.hide() break idx += 1 # This can fail if other interfaces are busted, so ignore errors used_by = None try: used_by = vmmCreateInterface.iface_in_use_by(self.conn, name) except Exception, e: logging.debug("Error looking up iface usage: %s", e) self.widget("interface-inuseby").set_text(used_by or "-") # IP info self.widget("interface-ipv4-expander").set_visible(bool(ipv4)) self.widget("interface-ipv6-expander").set_visible(bool(ipv6)) if ipv4: mode = ipv4[0] and "DHCP" or "Static" addr = ipv4[1] or "-" self.widget("interface-ipv4-mode").set_text(mode) self.widget("interface-ipv4-address").set_text(addr) if ipv6: mode = "" if ipv6[1]: mode = "Autoconf " if ipv6[0]: mode += "DHCP" else: mode = "Static" addrstr = "-" if ipv6[2]: addrstr = reduce(lambda x, y: x + "\n" + y, ipv6[2]) self.widget("interface-ipv6-mode").set_text(mode) self.widget("interface-ipv6-address").set_text(addrstr) self.widget("interface-delete").set_sensitive(not active) self.widget("interface-stop").set_sensitive(active) self.widget("interface-start").set_sensitive(not active) show_child = (children or itype in [Interface.INTERFACE_TYPE_BRIDGE, Interface.INTERFACE_TYPE_BOND]) self.widget("interface-child-box").set_visible(show_child) self.populate_interface_children() def refresh_interface(self, iface): iface_list = self.widget("interface-list") sel = iface_list.get_selection() model, treeiter = sel.get_selected() name = iface.get_name() for row in iface_list.get_model(): if row[0] == name: row[4] = iface.is_active() if treeiter is not None: if model[treeiter][0] == name: self.interface_selected(sel) def reset_interface_state(self): self.widget("interface-delete").set_sensitive(False) self.widget("interface-stop").set_sensitive(False) self.widget("interface-start").set_sensitive(False) self.widget("interface-apply").set_sensitive(False) def populate_interfaces(self, src=None, connkey=None): ignore = src ignore = connkey iface_list = self.widget("interface-list") curiface = self.current_interface() model = iface_list.get_model() # Prevent events while the model is modified iface_list.set_model(None) try: model.clear() iface_list.get_selection().unselect_all() for iface in self.conn.list_interfaces(): try: iface.disconnect_by_func(self.refresh_interface) except: pass iface.connect("state-changed", self.refresh_interface) model.append([iface.get_connkey(), iface.get_name(), "network-idle", Gtk.IconSize.LARGE_TOOLBAR, bool(iface.is_active())]) finally: iface_list.set_model(model) uiutil.set_list_selection(iface_list, curiface and curiface.get_connkey() or None) def populate_interface_children(self): interface = self.current_interface() child_list = self.widget("interface-child-list") model = child_list.get_model() child_list.get_selection().unselect_all() model.clear() if not interface: return for name, itype in interface.get_slaves(): row = [name, itype] model.append(row) 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() elif all([edit in EDIT_INTERFACE_IDS for edit in self.active_edits]): self.interface_apply() self.active_edits = [] return True