qubes-installer-qubes-os/anaconda/0004-anaconda-do-not-start-network-during-install-set-def.patch
2018-10-21 12:54:49 +02:00

1821 lines
73 KiB
Diff

From 7d67dbbb889a754c71a878fa69fcf2aa18fcdbb7 Mon Sep 17 00:00:00 2001
From: Marek Marczykowski <marmarek@invisiblethingslab.com>
Date: Fri, 19 Oct 2018 08:02:11 +0200
Subject: [PATCH] anaconda: do not start network during install, set default
hostname and write minimal network configuration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Frédéric Pierret <frederic.epitre@orange.fr>
---
pyanaconda/network.py | 14 +-
pyanaconda/ui/gui/spokes/network.py | 1750 -----------------------------------
2 files changed, 8 insertions(+), 1756 deletions(-)
delete mode 100644 pyanaconda/ui/gui/spokes/network.py
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index b92fb8acf..5d3dcd604 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -54,7 +54,7 @@ networkConfFile = "%s/network" % (sysconfigDir)
hostnameFile = "/etc/hostname"
ipv6ConfFile = "/etc/sysctl.d/anaconda.conf"
ifcfgLogFile = "/tmp/ifcfg.log"
-DEFAULT_HOSTNAME = "localhost.localdomain"
+DEFAULT_HOSTNAME = "dom0"
ifcfglog = None
@@ -1191,24 +1191,26 @@ def write_sysconfig_network(rootpath, overwrite=False):
with open(cfgfile, "w") as f:
f.write("# Created by anaconda\n")
+ f.write("NETWORKING=no\n")
return True
def write_network_config(storage, ksdata, instClass, rootpath):
# overwrite previous settings for LiveCD or liveimg installations
overwrite = flags.livecdInstall or ksdata.method.method == "liveimg"
- write_hostname(rootpath, ksdata, overwrite=overwrite)
+ write_hostname(rootpath, ksdata, overwrite=flags.livecdInstall)
if ksdata.network.hostname != DEFAULT_HOSTNAME:
set_hostname(ksdata.network.hostname)
- write_sysconfig_network(rootpath, overwrite=overwrite)
+ write_sysconfig_network(rootpath, overwrite=flags.livecdInstall)
disableIPV6(rootpath)
copyIfcfgFiles(rootpath)
copyDhclientConfFiles(rootpath)
copyFileToPath("/etc/resolv.conf", rootpath, overwrite=overwrite)
- instClass.setNetworkOnbootDefault(ksdata)
- autostartFCoEDevices(rootpath, storage, ksdata)
-def update_hostname_data(ksdata, hostname):
+def update_hostname_data(ksdata, hostname=None):
+ if not hostname:
+ # Default to 'dom0' in Qubes
+ hostname = 'dom0'
log.debug("updating host name %s", hostname)
hostname_found = False
for nd in ksdata.network.network:
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
deleted file mode 100644
index a15a07ccb..000000000
--- a/pyanaconda/ui/gui/spokes/network.py
+++ /dev/null
@@ -1,1750 +0,0 @@
-# Network configuration spoke classes
-#
-# Copyright (C) 2011 Red Hat, Inc.
-#
-# This copyrighted material is made available to anyone wishing to use,
-# modify, copy, or redistribute it subject to the terms and conditions of
-# the GNU General Public License v.2, or (at your option) any later version.
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY expressed or implied, including the implied warranties 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. Any Red Hat trademarks that are incorporated in the
-# source code or documentation are not subject to the GNU General Public
-# License and may only be used or replicated with the express permission of
-# Red Hat, Inc.
-#
-
-import gi
-gi.require_version("Gtk", "3.0")
-gi.require_version("GLib", "2.0")
-gi.require_version("GObject", "2.0")
-gi.require_version("Pango", "1.0")
-gi.require_version("Gio", "2.0")
-gi.require_version("NM", "1.0")
-
-from gi.repository import Gtk
-from gi.repository import GLib, GObject, Pango, Gio, NM
-
-from pyanaconda.flags import can_touch_runtime_system
-from pyanaconda.i18n import _, N_, C_, CN_
-from pyanaconda.flags import flags as anaconda_flags
-from pyanaconda.ui.communication import hubQ
-from pyanaconda.ui.gui import GUIObject
-from pyanaconda.ui.gui.spokes import NormalSpoke, StandaloneSpoke
-from pyanaconda.ui.categories.system import SystemCategory
-from pyanaconda.ui.gui.hubs.summary import SummaryHub
-from pyanaconda.ui.gui.utils import gtk_call_once, escape_markup, really_hide, really_show
-from pyanaconda.ui.common import FirstbootSpokeMixIn
-from pyanaconda.iutil import startProgram
-from pyanaconda.constants import ANACONDA_ENVIRON
-
-from pyanaconda import network
-from pyanaconda import nm
-
-import dbus
-import dbus.service
-# Used for ascii_letters and hexdigits constants
-import string # pylint: disable=deprecated-module
-from uuid import uuid4
-
-from dbus.mainloop.glib import DBusGMainLoop
-DBusGMainLoop(set_as_default=True)
-
-import logging
-log = logging.getLogger("anaconda")
-
-NM._80211ApFlags = getattr(NM, "80211ApFlags")
-NM._80211ApSecurityFlags = getattr(NM, "80211ApSecurityFlags")
-NM._80211Mode = getattr(NM, "80211Mode")
-
-NM_SERVICE = "org.freedesktop.NetworkManager"
-NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1
-SECRET_AGENT_IFACE = 'org.freedesktop.NetworkManager.SecretAgent'
-AGENT_MANAGER_IFACE = 'org.freedesktop.NetworkManager.AgentManager'
-AGENT_MANAGER_PATH = "/org/freedesktop/NetworkManager/AgentManager"
-
-IPV4_CONFIG = "IPv4"
-IPV6_CONFIG = "IPv6"
-
-DEVICES_COLUMN_TITLE = 2
-DEVICES_COLUMN_OBJECT = 3
-
-nmclient = NM.Client.new()
-
-def localized_string_of_device_state(device, state):
- s = _("Status unknown (missing)")
-
- if state == NM.DeviceState.UNKNOWN:
- s = _("Status unknown")
- elif state == NM.DeviceState.UNMANAGED:
- s = _("Unmanaged")
- elif state == NM.DeviceState.UNAVAILABLE:
- if not device:
- s = _("Unavailable")
- elif device.get_firmware_missing():
- s = _("Firmware missing")
- else:
- s = _("Unavailable")
- elif state == NM.DeviceState.DISCONNECTED:
- if (device and device.get_device_type() == NM.DeviceType.ETHERNET
- and not device.get_carrier()):
- s = _("Cable unplugged")
- else:
- s = _("Disconnected")
- elif state in (NM.DeviceState.PREPARE,
- NM.DeviceState.CONFIG,
- NM.DeviceState.IP_CONFIG,
- NM.DeviceState.IP_CHECK):
- s = _("Connecting")
- elif state == NM.DeviceState.NEED_AUTH:
- s = _("Authentication required")
- elif state == NM.DeviceState.ACTIVATED:
- s = _("Connected")
- elif state == NM.DeviceState.DEACTIVATING:
- s = _("Disconnecting")
- elif state == NM.DeviceState.FAILED:
- s = _("Connection failed")
-
- return s
-
-__all__ = ["NetworkSpoke", "NetworkStandaloneSpoke"]
-
-class CellRendererSignal(Gtk.CellRendererPixbuf):
-
- __gtype_name__ = "CellRendererSignal"
- __gproperties__ = {
- "signal": (GObject.TYPE_UINT,
- "Signal", "Signal",
- 0, GObject.G_MAXUINT, 0,
- GObject.PARAM_READWRITE),
- }
-
- def __init__(self):
- Gtk.CellRendererPixbuf.__init__(self)
- self.signal = 0
-
-
- def do_get_property(self, prop):
- if prop.name == 'signal':
- return self.signal
- else:
- raise AttributeError('unknown property %s' % prop.name)
-
- def do_set_property(self, prop, value):
- if prop.name == 'signal':
- self.signal = value
- self._set_icon_name(value)
- else:
- raise AttributeError('unknown property %s' % prop.name)
-
- def _set_icon_name(self, value):
-
- if value == 0:
- self.set_property("gicon", None)
-
- if value < 20:
- icon_name = "network-wireless-signal-none-symbolic"
- elif value < 40:
- icon_name = "network-wireless-signal-weak-symbolic"
- elif value < 50:
- icon_name = "network-wireless-signal-ok-symbolic"
- elif value < 80:
- icon_name = "network-wireless-signal-good-symbolic"
- else:
- icon_name = "network-wireless-signal-excellent-symbolic"
-
- icon = Gio.ThemedIcon.new_with_default_fallbacks(icon_name)
- self.set_property("gicon", icon)
-
-
-NM_AP_SEC_UNKNOWN = 0
-NM_AP_SEC_NONE = 1
-NM_AP_SEC_WEP = 2
-NM_AP_SEC_WPA = 3
-NM_AP_SEC_WPA2 = 4
-
-class CellRendererSecurity(Gtk.CellRendererPixbuf):
-
- __gtype_name__ = "CellRendererSecurity"
- __gproperties__ = {
- "security": (GObject.TYPE_UINT,
- "Security", "Security",
- 0, GObject.G_MAXUINT, 0,
- GObject.PARAM_READWRITE),
- }
-
- def __init__(self):
- Gtk.CellRendererPixbuf.__init__(self)
- self.security = NM_AP_SEC_UNKNOWN
- self.icon_name = ""
-
- def do_get_property(self, prop):
- if prop.name == 'security':
- return self.security
- else:
- raise AttributeError('unknown property %s' % prop.name)
-
- def do_set_property(self, prop, value):
- if prop.name == 'security':
- self.security = value
- self._set_icon_name(value)
- else:
- raise AttributeError('unknown property %s' % prop.name)
-
- def _set_icon_name(self, security):
- self.icon_name = ""
- if security not in (NM_AP_SEC_NONE, NM_AP_SEC_UNKNOWN):
- self.icon_name = "network-wireless-encrypted-symbolic"
-
- self.set_property("icon-name", self.icon_name)
-
-class DeviceConfiguration(object):
-
- setting_types = {
- '802-11-wireless': NM.DeviceType.WIFI,
- '802-3-ethernet': NM.DeviceType.ETHERNET,
- 'vlan': NM.DeviceType.VLAN,
- 'bond': NM.DeviceType.BOND,
- 'team': NM.DeviceType.TEAM,
- 'bridge': NM.DeviceType.BRIDGE,
- }
-
- def __init__(self, device=None, con=None):
- self.device = device
- self.con = con
-
- def get_device_type(self):
- if self.device:
- return self.device.get_device_type()
- elif self.con:
- return self.setting_types.get(self.con.get_connection_type(), None)
- else:
- return None
-
- def get_iface(self):
- iface = None
- if self.device:
- iface = self.device.get_iface()
- elif self.con:
- iface = self.con.get_setting_connection().get_interface_name()
- wired_setting = self.con.get_setting_wired()
- if not iface and wired_setting:
- mac = wired_setting.get_mac_address()
- if mac:
- iface = nm.nm_hwaddr_to_device_name(mac)
- return iface
-
- def get_uuid(self):
- return self.con and self.con.get_uuid()
-
-class NetworkControlBox(GObject.GObject):
-
- __gsignals__ = {
- "nm-state-changed": (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, []),
- "device-state-changed": (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, [str, int, int, int]),
- "apply-hostname": (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, []),
- }
-
- supported_device_types = [
- NM.DeviceType.ETHERNET,
- NM.DeviceType.WIFI,
- NM.DeviceType.TEAM,
- NM.DeviceType.BOND,
- NM.DeviceType.VLAN,
- NM.DeviceType.BRIDGE,
- ]
-
- wired_ui_device_types = [
- NM.DeviceType.ETHERNET,
- NM.DeviceType.TEAM,
- NM.DeviceType.BOND,
- NM.DeviceType.VLAN,
- NM.DeviceType.BRIDGE,
- ]
-
- device_type_sort_value = {
- NM.DeviceType.ETHERNET : "1",
- NM.DeviceType.WIFI : "2",
- }
-
- device_type_name = {
- NM.DeviceType.UNKNOWN: N_("Unknown"),
- NM.DeviceType.ETHERNET: N_("Ethernet"),
- NM.DeviceType.WIFI: N_("Wireless"),
- NM.DeviceType.BOND: N_("Bond"),
- NM.DeviceType.VLAN: N_("VLAN"),
- NM.DeviceType.TEAM: N_("Team"),
- NM.DeviceType.BRIDGE: N_("Bridge"),
- }
-
- def __init__(self, builder, client, spoke=None):
-
- GObject.GObject.__init__(self)
-
- self.builder = builder
- self._running_nmce = None
- self.spoke = spoke
- self.client = client
-
- # button for creating of virtual bond and vlan devices
- self.builder.get_object("add_toolbutton").set_sensitive(True)
- self.builder.get_object("add_toolbutton").connect("clicked",
- self.on_add_device_clicked)
- self.builder.get_object("remove_toolbutton").set_sensitive(False)
- self.builder.get_object("remove_toolbutton").connect("clicked",
- self.on_remove_device_clicked)
-
- not_supported = ["start_hotspot_button",
- "stop_hotspot_button",
- "heading_hotspot_network_name",
- "heading_hotspot_security_key",
- "label_hotspot_network_name",
- "label_hotspot_security_key",
- "hbox54",
- ]
-
- do_not_show_in_refresh = ["heading_wireless_network_name",
- "combobox_wireless_network_name"]
- do_not_show_in_refresh += ["%s_%s_%s" % (widget, ty, value)
- for widget in ["heading", "label"]
- for ty in ["wired", "wireless"]
- for value in ["ipv4", "ipv6", "dns", "route"]]
- do_not_show_in_refresh += ["%s_wired_%s" % (widget, value)
- for widget in ["heading", "label"]
- for value in ["slaves", "vlanid", "parent"]]
-
- for ident in not_supported + do_not_show_in_refresh:
- self.builder.get_object(ident).set_no_show_all(True)
- self.builder.get_object(ident).hide()
-
- self.builder.get_object("notebook_types").set_show_tabs(False)
-
- # to prevent UI update signals races
- self._updating_device = False
-
- # devices list
- # limited to wired and wireless
- treeview = self.builder.get_object("treeview_devices")
- self._add_device_columns(treeview)
- self.dev_cfg_store = self.builder.get_object("liststore_devices")
- self.dev_cfg_store.set_sort_column_id(2, Gtk.SortType.ASCENDING)
- selection = treeview.get_selection()
- selection.set_mode(Gtk.SelectionMode.BROWSE)
- selection.connect("changed", self.on_device_selection_changed)
-
- # wireless APs list
- combobox = self.builder.get_object("combobox_wireless_network_name")
- self._add_ap_icons(combobox)
- model = combobox.get_model()
- model.set_sort_column_id(2, Gtk.SortType.ASCENDING)
- combobox.connect("changed", self.on_wireless_ap_changed_cb)
- self.selected_ap = None
-
- self.builder.get_object("device_wired_off_switch").connect("notify::active",
- self.on_device_off_toggled)
- self.builder.get_object("device_wireless_off_switch").connect("notify::active",
- self.on_device_off_toggled)
- self.builder.get_object("button_wired_options").connect("clicked",
- self.on_edit_connection)
- self.builder.get_object("button_wireless_options").connect("clicked",
- self.on_edit_connection)
- self.entry_hostname = self.builder.get_object("entry_hostname")
- self.label_current_hostname = self.builder.get_object("label_current_hostname")
- self.button_apply_hostname = self.builder.get_object("button_apply_hostname")
- self.button_apply_hostname.connect("clicked", self.on_apply_hostname)
-
- @property
- def vbox(self):
- return self.builder.get_object("networkControlBox_vbox")
-
-
- def _add_ap_icons(self, combobox):
- cell = CellRendererSecurity()
- cell.set_padding(4, 0)
- combobox.pack_start(cell, False)
- combobox.add_attribute(cell, "security", 5)
-
- cell = CellRendererSignal()
- cell.set_padding(4, 0)
- #cell.set_property("xalign", 1.0)
- combobox.pack_start(cell, False)
- combobox.add_attribute(cell, "signal", 3)
-
- def _add_device_columns(self, treeview):
- rnd = Gtk.CellRendererPixbuf()
- rnd.set_property("stock-size", Gtk.IconSize.DND)
- # TODO Gtk3 icon-name? (also at other places)
- col = Gtk.TreeViewColumn("Icon", rnd, **{"icon-name":0})
- treeview.append_column(col)
-
- rnd = Gtk.CellRendererText()
- rnd.set_property("wrap-mode", Pango.WrapMode.WORD)
- col = Gtk.TreeViewColumn("Text", rnd, markup=2)
- col.set_sort_column_id(2)
- col.set_expand(True)
- treeview.append_column(col)
-
- def add_connection_to_list(self, con):
- uuid = con.get_uuid()
- if self.dev_cfg(uuid=uuid):
- log.debug("network: GUI, not adding connection %s, already in list", uuid)
- return False
- con_setting = con.get_setting_connection()
- if con_setting and con_setting.get_read_only():
- log.debug("network: GUI, not adding read-only connection %s", uuid)
- return False
- dev_cfg = DeviceConfiguration(con=con)
- if network.is_libvirt_device(dev_cfg.get_iface() or ""):
- log.debug("network: GUI, not adding %s", dev_cfg.get_iface())
- return False
- if network.is_ibft_configured_device(dev_cfg.get_iface() or ""):
- log.debug("network: GUI, not adding %s configured from iBFT", dev_cfg.get_iface())
- return False
- if dev_cfg.get_device_type() not in self.supported_device_types:
- log.debug("network: GUI, not adding connection %s of unsupported type", uuid)
- return False
- if dev_cfg.get_device_type() == NM.DeviceType.ETHERNET:
- if con_setting and con_setting.get_master():
- log.debug("network: GUI, not adding slave connection %s", uuid)
- return False
- # Wireless settings are handled in scope of its device's dev_cfg
- if dev_cfg.get_device_type() == NM.DeviceType.WIFI:
- log.debug("network: GUI, not adding wireless connection %s", uuid)
- return False
- existing_dev_cfg = self.dev_cfg(iface=dev_cfg.get_iface())
- if existing_dev_cfg:
- if existing_dev_cfg.con:
- log.debug("network: GUI, not adding connection %s, already have %s for device %s",
- uuid, existing_dev_cfg.get_uuid(), existing_dev_cfg.device.get_iface())
- return False
- else:
- log.debug("network: GUI, attaching connection %s to device %s",
- uuid, existing_dev_cfg.device.get_iface())
- existing_dev_cfg.con = con
- else:
- log.debug("network: GUI, adding connection %s", uuid)
- self.add_dev_cfg(dev_cfg)
- return True
-
- def initialize(self):
- self.client.connect("device-added", self.on_device_added)
- self.client.connect("device-removed", self.on_device_removed)
- self.client.connect("connection-added", self.on_connection_added)
- self.client.connect("notify::%s" % NM.CLIENT_WIRELESS_ENABLED,
- self.on_wireless_enabled)
- self.client.connect("notify::%s" % NM.CLIENT_STATE,
- self.on_nm_state_changed)
-
- for device in self.client.get_devices():
- self.add_device_to_list(device)
-
- for con in self.client.get_connections():
- self.add_connection_to_list(con)
-
- # select the first device
- treeview = self.builder.get_object("treeview_devices")
- selection = treeview.get_selection()
- itr = self.dev_cfg_store.get_iter_first()
- if itr:
- selection.select_iter(itr)
-
- def refresh(self):
- self.refresh_ui()
-
- # Signal handlers.
- def on_nm_state_changed(self, *args):
- self.emit("nm-state-changed")
-
- def on_device_selection_changed(self, *args):
- self.refresh_ui()
-
- def on_device_state_changed(self, device, new_state, *args):
- self.emit("device-state-changed", device.get_iface(), new_state, *args)
- if new_state == NM.DeviceState.SECONDARIES:
- return
- self._refresh_carrier_info()
- dev_cfg = self.selected_dev_cfg()
- if dev_cfg and dev_cfg.device == device:
- self.refresh_ui(state=new_state)
-
- def on_device_config_changed(self, device, *args):
- dev_cfg = self.selected_dev_cfg()
- if dev_cfg and dev_cfg.device == device:
- self.refresh_ui()
-
- def on_wireless_ap_changed_cb(self, combobox, *args):
- if self._updating_device:
- return
- itr = combobox.get_active_iter()
- if not itr:
- return
-
- dev_cfg = self.selected_dev_cfg()
- if not dev_cfg:
- return
-
- device = dev_cfg.device
-
- ap, ssid_target = combobox.get_model().get(itr, 0, 1)
- self.selected_ap = ap
-
- log.info("network: selected access point: %s", ssid_target)
-
- cons = ap.filter_connections(device.filter_connections(self.client.get_connections()))
- if cons:
- con = cons[0]
- self.client.activate_connection_async(con, device, ap.get_path(), None)
- else:
- if self._ap_is_enterprise(ap):
- # Create a connection for the ap and [Configure] it later with nm-c-e
- con = NM.SimpleConnection.new()
- s_con = NM.SettingConnection.new()
- s_con.set_property('uuid', str(uuid4()))
- s_con.set_property('id', ssid_target)
- s_con.set_property('type', '802-11-wireless')
- s_wireless = NM.SettingWireless.new()
- s_wireless.set_property('ssid', ap.get_ssid())
- s_wireless.set_property('mode', 'infrastructure')
- log.debug("network: adding connection for WPA-Enterprise AP %s", ssid_target)
- con.add_setting(s_con)
- con.add_setting(s_wireless)
- persistent = True
- self.client.add_connection_async(con, persistent, None)
- self.builder.get_object("button_wireless_options").set_sensitive(True)
- else:
- self.client.add_and_activate_connection_async(None, device, ap.get_path(), None)
-
- def on_connection_added(self, client, connection):
- self.add_connection_to_list(connection)
-
- def on_device_added(self, client, device, *args):
- # We need to wait for valid state before adding the device to our list
- if device.get_state() == NM.DeviceState.UNKNOWN:
- device.connect("state-changed", self.on_added_device_state_changed)
- else:
- self.add_device_to_list(device)
-
- def on_added_device_state_changed(self, device, new_state, *args):
- # We need to wait for valid state before adding the device to our list
- if new_state != NM.DeviceState.UNKNOWN:
- device.disconnect_by_func(self.on_added_device_state_changed)
- self.add_device_to_list(device)
-
- def on_device_removed(self, client, device, *args):
- self.remove_device(device)
-
- def _find_first_ap_setting(self, device, ap):
- for con in device.filter_connections(self.client.get_connections()):
- wireless_setting = con.get_setting_wireless()
- if not wireless_setting or not wireless_setting.get_ssid():
- # setting is None or non-broadcast AP, we ignore these
- return
- if wireless_setting.get_ssid().get_data() == ap.get_ssid().get_data():
- return con
-
- def on_edit_connection(self, *args):
- dev_cfg = self.selected_dev_cfg()
- if not dev_cfg:
- return
-
- device = dev_cfg.device
- con = dev_cfg.con
- activate = None
- ssid = ""
-
- if dev_cfg.get_device_type() == NM.DeviceType.WIFI:
- if not self.selected_ap:
- return
- ssid = self.selected_ap.get_ssid().get_data()
- con = self._find_first_ap_setting(device, self.selected_ap)
- if not con:
- log.debug("network: on_edit_connection: connection for ap %s not found", self.selected_ap)
- return
- # 871132 auto activate wireless connection after editing if it is not
- # already activated (assume entering secrets)
- condition = lambda: self.selected_ap != device.get_active_access_point()
- activate = (con, device, condition)
- else:
- if not con:
- log.debug("network: on_edit_connection: connection for device %s not found", device.get_iface())
- if dev_cfg.get_device_type() == NM.DeviceType.ETHERNET:
- # Create default connection for the device and run nm-c-e on it
- default_con = self._default_eth_con(device.get_iface(), autoconnect=False)
- persistent = False
- log.info("network: creating new connection for %s device", dev_cfg.get_iface())
- self.client.add_connection_async(default_con, persistent, None,
- self._default_connection_added_cb, activate)
- return
-
- if device and device.get_state() == NM.DeviceState.ACTIVATED:
- # Reactivate the connection after configuring it (if it changed)
- settings = con.to_dbus(NM.ConnectionSerializationFlags.ALL)
- settings_changed = lambda: settings != con.to_dbus(NM.ConnectionSerializationFlags.ALL)
- activate = (con, device, settings_changed)
-
- log.info("network: configuring connection %s device %s ssid %s",
- con.get_uuid(), dev_cfg.get_iface(), ssid)
- self._run_nmce(con.get_uuid(), activate)
-
- def _default_connection_added_cb(self, client, result, activate):
- con = client.add_connection_finish(result)
- uuid = con.get_setting_connection().get_uuid()
- log.info("network: configuring new connection %s", uuid)
- self._run_nmce(uuid, activate)
-
- def _run_nmce(self, uuid, activate):
- self.kill_nmce(msg="Configure button clicked")
- proc = startProgram(["nm-connection-editor", "--keep-above", "--edit", "%s" % uuid], reset_lang=False)
- self._running_nmce = proc
-
- GLib.child_watch_add(proc.pid, self.on_nmce_exited, activate)
-
- def _default_eth_con(self, iface, autoconnect):
- con = NM.SimpleConnection.new()
- s_con = NM.SettingConnection.new()
- s_con.set_property('uuid', str(uuid4()))
- s_con.set_property('id', iface)
- s_con.set_property('interface-name', iface)
- s_con.set_property('autoconnect', autoconnect)
- s_con.set_property('type', '802-3-ethernet')
- s_wired = NM.SettingWired.new()
- con.add_setting(s_con)
- con.add_setting(s_wired)
- return con
-
- def kill_nmce(self, msg=""):
- if not self._running_nmce:
- return False
-
- log.debug("network: killing running nm-c-e %s: %s", self._running_nmce.pid, msg)
- self._running_nmce.kill()
- self._running_nmce = None
- return True
-
- def on_nmce_exited(self, pid, condition, activate=None):
- # waitpid() has been called, make sure we don't do anything else with the proc
- self._running_nmce = None
- log.debug("nm-c-e exited with status %s", condition)
-
- # nm-c-e was closed normally, not killed by anaconda
- if condition == 0:
- if activate:
- # The default of None confuses pylint
- con, device, activate_condition = activate # pylint: disable=unpacking-non-sequence
- if activate_condition():
- gtk_call_once(self._activate_connection_cb, con, device)
- network.logIfcfgFiles("nm-c-e run")
-
- def _activate_connection_cb(self, con, device):
- self.client.activate_connection_async(con, device, None, None)
- if self.spoke:
- self.spoke.networking_changed = True
-
- def on_wireless_enabled(self, *args):
- switch = self.builder.get_object("device_wireless_off_switch")
- self._updating_device = True
- switch.set_active(self.client.wireless_get_enabled())
- self._updating_device = False
-
- def on_device_off_toggled(self, switch, *args):
- if self._updating_device:
- return
-
- active = switch.get_active()
- dev_cfg = self.selected_dev_cfg()
- if not dev_cfg:
- return
- device = dev_cfg.device
- con = dev_cfg.con
-
- log.info("network: device %s switched %s", dev_cfg.get_iface(), "on" if active else "off")
-
- if dev_cfg.get_device_type() == NM.DeviceType.WIFI:
- self.client.wireless_set_enabled(active)
- else:
- if active:
- if not con:
- log.debug("network: on_device_off_toggled: no connection for %s",
- dev_cfg.get_iface())
- return
-
- self.client.activate_connection_async(con, device, None, None)
- else:
- if not device:
- log.debug("network: on_device_off_toggled: no device for %s", dev_cfg.get_iface())
- return
- device.disconnect(None)
-
- if self.spoke:
- self.spoke.networking_changed = True
-
- def on_add_device_clicked(self, *args):
- dialog = self.builder.get_object("add_device_dialog")
- with self.spoke.main_window.enlightbox(dialog):
- rc = dialog.run()
- dialog.hide()
- if rc == 1:
- ai = self.builder.get_object("combobox_add_device").get_active_iter()
- model = self.builder.get_object("liststore_add_device")
- dev_type = model[ai][1]
- self.add_device(dev_type)
-
- def on_remove_device_clicked(self, *args):
- selection = self.builder.get_object("treeview_devices").get_selection()
- model, itr = selection.get_selected()
- if not itr:
- return None
- dev_cfg = model[itr][DEVICES_COLUMN_OBJECT]
- model.remove(itr)
- if dev_cfg.con:
- dev_cfg.con.delete()
-
- def on_apply_hostname(self, *args):
- self.emit("apply-hostname")
-
- def add_device(self, ty):
- log.info("network: adding device of type %s", ty)
- self.kill_nmce(msg="Add device button clicked")
- proc = startProgram(["nm-connection-editor", "--keep-above", "--create", "--type=%s" % ty], reset_lang=False)
- self._running_nmce = proc
-
- GLib.child_watch_add(proc.pid, self.on_nmce_exited)
-
- def selected_dev_cfg(self):
- selection = self.builder.get_object("treeview_devices").get_selection()
- model, itr = selection.get_selected()
- if not itr:
- return None
- return model[itr][DEVICES_COLUMN_OBJECT]
-
- def add_dev_cfg(self, dev_cfg):
- log.debug("network: GUI, device configuration added: connection %s device %s",
- dev_cfg.get_uuid(), dev_cfg.get_iface())
- self.dev_cfg_store.append([
- self._dev_icon_name(dev_cfg),
- self.device_type_sort_value.get(dev_cfg.get_device_type(), "100"),
- self._dev_title(dev_cfg),
- dev_cfg
- ])
-
- def add_device_to_list(self, device):
- if device.get_device_type() not in self.supported_device_types:
- return
- if network.is_libvirt_device(device.get_iface()):
- log.debug("network: not adding %s", device.get_iface())
- return
- # ignore fcoe vlan devices
- # (can be chopped off to IFNAMSIZ kernel limit)
- if device.get_iface().endswith(('-fcoe', '-fco', '-fc', '-f', '-')):
- return
- if network.is_ibft_configured_device(device.get_iface() or ""):
- log.debug("network: not adding connection for device %s configured from iBFT", device.get_iface())
- return False
-
- # Ignore devices with active read-only connections (created by NM for iBFT VLAN)
- ac = device.get_active_connection()
- if ac:
- rc = ac.get_connection()
- # Getting of NMRemoteConnection can fail (None), isn't it a bug in NM?
- if rc:
- con_setting = rc.get_setting_connection()
- if con_setting and con_setting.get_read_only():
- log.debug("network: not adding read-only connection "
- "(assuming iBFT) for device %s", device.get_iface())
- return
- else:
- log.debug("network: can't get remote connection of active connection "
- "of device %s", device.get_iface())
-
- # Find the connection for the device (assuming existence of single ifcfg actually)
- con = None
- # Wifi connections are stored in wifi tab combobox
- if device.get_device_type() != NM.DeviceType.WIFI:
- cons = device.get_available_connections()
- for c in cons:
- if c.get_setting_connection() and not c.get_setting_connection().get_slave_type():
- con = c
- if len(cons) != 1:
- log.warning("network: %s has unexpected number of connections: %s",
- device.get_iface(), [c.get_uuid() for c in cons])
-
- if con and self.dev_cfg(uuid=con.get_uuid()):
- # If we already have a connection for the device
- # it is a virtual device appearing
- self.dev_cfg(uuid=con.get_uuid()).device = device
- # it might be too late for the callbacks below so refresh now
- self.refresh_ui()
- else:
- self.add_dev_cfg(DeviceConfiguration(device=device, con=con))
-
- device.connect("notify::ip4-config", self.on_ip_obj_changed, IPV4_CONFIG)
- device.connect("notify::ip6-config", self.on_ip_obj_changed, IPV6_CONFIG)
- device.connect("state-changed", self.on_device_state_changed)
-
- def on_ip_obj_changed(self, device, *args):
- """Callback when ipX-config objects will be changed.
-
- Register callback on properties (IP address, gateway...) of these ipX-config
- objects when they are created.
- """
- log.debug("network: %s object changed", args[1])
- self.on_device_config_changed(device)
- if args[1] == IPV4_CONFIG:
- config = device.props.ip4_config
- else:
- config = device.props.ip6_config
-
- if config:
- # register callback when inner NMIP[4,6]Config object changed
- config.connect("notify::addresses", self.on_config_changed, device)
- config.connect("notify::gateway", self.on_config_changed, device)
- config.connect("notify::nameservers", self.on_config_changed, device)
-
- def on_config_changed(self, config, *args):
- """Callback on property change of ipX-config objects.
-
- Call method which show changed properties (IP, gateway...) to an user.
- """
- self.on_device_config_changed(args[1])
-
- def _dev_icon_name(self, dev_cfg):
- icon_name = ""
- if dev_cfg.get_device_type() in self.wired_ui_device_types:
- if dev_cfg.device:
- if dev_cfg.device.get_state() == NM.DeviceState.UNAVAILABLE:
- icon_name = "network-wired-disconnected"
- else:
- icon_name = "network-wired"
- else:
- icon_name = "network-wired-disconnected"
- elif dev_cfg.get_device_type() == NM.DeviceType.WIFI:
- icon_name = "network-wireless"
-
- return icon_name
-
- def _dev_title(self, dev_cfg):
- unplugged = ''
-
- if dev_cfg.device:
- if (dev_cfg.device.get_state() == NM.DeviceState.UNAVAILABLE
- and dev_cfg.device.get_device_type() == NM.DeviceType.ETHERNET
- and not dev_cfg.device.get_carrier()):
- # TRANSLATORS: ethernet cable is unplugged
- unplugged = ', <i>%s</i>' % escape_markup(_("unplugged"))
- # pylint: disable=unescaped-markup
- title = '<span size="large">%s (%s%s)</span>' % \
- (escape_markup(_(self.device_type_name.get(dev_cfg.get_device_type(), ""))),
- escape_markup(dev_cfg.get_iface()),
- unplugged)
-
- if dev_cfg.device:
- title += '\n<span size="small">%s %s</span>' % \
- (escape_markup(dev_cfg.device.get_vendor() or ""),
- escape_markup(dev_cfg.device.get_product() or ""))
- return title
-
- def dev_cfg(self, uuid=None, device=None, iface=None):
- for row in self.dev_cfg_store:
- dev_cfg = row[DEVICES_COLUMN_OBJECT]
- if uuid:
- if dev_cfg.get_uuid() != uuid:
- continue
- if device:
- if not dev_cfg.device \
- or dev_cfg.device.get_udi() != device.get_udi():
- continue
- if iface:
- if not dev_cfg.device \
- or dev_cfg.device.get_iface() != iface:
- continue
- return dev_cfg
- return None
-
- def remove_device(self, device):
- # This should not concern wifi and ethernet devices,
- # just virtual devices e.g. vpn probably
- log.debug("network: GUI, device removed: %s", device.get_iface())
- if self.spoke:
- self.spoke.networking_changed = True
- dev_cfg = self.dev_cfg(device=device)
- if dev_cfg:
- dev_cfg.device = None
-
- def refresh_ui(self, state=None):
-
- dev_cfg = self.selected_dev_cfg()
- if not dev_cfg:
- # the list is empty (no supported devices)
- notebook = self.builder.get_object("notebook_types")
- notebook.set_current_page(5)
- return
-
- self._refresh_device_type_page(dev_cfg.get_device_type())
- self._refresh_header_ui(dev_cfg, state)
- self._refresh_slaves(dev_cfg)
- self._refresh_parent_vlanid(dev_cfg)
- self._refresh_speed_hwaddr(dev_cfg, state)
- self._refresh_ap(dev_cfg, state)
- self._refresh_device_cfg(dev_cfg)
-
- def _refresh_device_cfg(self, dev_cfg):
-
- if dev_cfg.get_device_type() in self.wired_ui_device_types:
- dt = "wired"
- elif dev_cfg.get_device_type() == NM.DeviceType.WIFI:
- dt = "wireless"
-
- if dev_cfg.device:
- ipv4cfg = dev_cfg.device.get_ip4_config()
- ipv6cfg = dev_cfg.device.get_ip6_config()
- else:
- ipv4cfg = ipv6cfg = None
-
- if ipv4cfg:
- addr_str = ",".join("%s/%d" % (a.get_address(), a.get_prefix())
- for a in ipv4cfg.get_addresses())
- gateway_str = ipv4cfg.get_gateway()
- dnss_str = ",".join(ipv4cfg.get_nameservers())
- else:
- addr_str = dnss_str = gateway_str = None
- self._set_device_info_value(dt, "ipv4", addr_str)
- self._set_device_info_value(dt, "dns", dnss_str)
- self._set_device_info_value(dt, "route", gateway_str)
-
- addr6_str = ""
- if ipv6cfg:
- addr6_str = ",".join("%s/%d" % (a.get_address(), a.get_prefix())
- for a in ipv6cfg.get_addresses()
- # Do not display link-local addresses
- if not a.get_address().startswith("fe80:"))
- self._set_device_info_value(dt, "ipv6", addr6_str.strip() or None)
-
- if ipv4cfg and addr6_str:
- self.builder.get_object("heading_%s_ipv4" % dt).set_label(_("IPv4 Address"))
- self.builder.get_object("heading_%s_ipv6" % dt).set_label(_("IPv6 Address"))
- elif ipv4cfg:
- self.builder.get_object("heading_%s_ipv4" % dt).set_label(_("IP Address"))
- elif addr6_str:
- self.builder.get_object("heading_%s_ipv6" % dt).set_label(_("IP Address"))
-
- return False
-
- def _refresh_ap(self, dev_cfg, state=None):
- if dev_cfg.get_device_type() != NM.DeviceType.WIFI:
- return
-
- if state is None:
- state = dev_cfg.device.get_state()
- if state == NM.DeviceState.UNAVAILABLE:
- ap_str = None
- else:
- active_ap = dev_cfg.device.get_active_access_point()
- if active_ap:
- ap_str = self._ap_security_string(active_ap)
- else:
- ap_str = ""
-
- self._set_device_info_value("wireless", "security", ap_str)
-
- if state == NM.DeviceState.UNAVAILABLE:
- self.builder.get_object("heading_wireless_network_name").hide()
- self.builder.get_object("combobox_wireless_network_name").hide()
- else:
- self.builder.get_object("heading_wireless_network_name").show()
- self.builder.get_object("combobox_wireless_network_name").show()
-
- store = self.builder.get_object("liststore_wireless_network")
- self._updating_device = True
- store.clear()
- aps = self._get_strongest_unique_aps(dev_cfg.device.get_access_points())
- for ap in aps:
- self._add_ap(ap, active_ap == ap)
- # TODO: add access point other...
- if active_ap:
- combobox = self.builder.get_object("combobox_wireless_network_name")
- for i in combobox.get_model():
- if i[0] == active_ap:
- combobox.set_active_iter(i.iter)
- self.selected_ap = active_ap
- break
- self._updating_device = False
-
- def _refresh_slaves(self, dev_cfg):
- if dev_cfg.get_device_type() in [NM.DeviceType.BOND,
- NM.DeviceType.TEAM,
- NM.DeviceType.BRIDGE]:
- slaves = ""
- if dev_cfg.device:
- slaves = ",".join(s.get_iface() for s in dev_cfg.device.get_slaves())
- self._set_device_info_value("wired", "slaves", slaves)
-
- def _refresh_parent_vlanid(self, dev_cfg):
- if dev_cfg.get_device_type() == NM.DeviceType.VLAN:
- if dev_cfg.device:
- vlanid = dev_cfg.device.get_vlan_id()
- else:
- vlanid = dev_cfg.con.get_setting_vlan().get_id()
- parent = dev_cfg.con.get_setting_vlan().get_parent()
- self._set_device_info_value("wired", "vlanid", str(vlanid))
- self._set_device_info_value("wired", "parent", parent)
-
- def _refresh_speed_hwaddr(self, dev_cfg, state=None):
- dev_type = dev_cfg.get_device_type()
- if dev_type in self.wired_ui_device_types:
- dt = "wired"
- elif dev_type == NM.DeviceType.WIFI:
- dt = "wireless"
-
- # Speed
- speed = None
- if dev_cfg.device:
- if dev_type == NM.DeviceType.ETHERNET:
- speed = dev_cfg.device.get_speed()
- elif dev_type == NM.DeviceType.WIFI:
- speed = dev_cfg.device.get_bitrate() / 1000
- if state is None:
- state = dev_cfg.device.get_state()
-
- if not dev_cfg.device or state == NM.DeviceState.UNAVAILABLE:
- speed_str = None
- elif speed:
- speed_str = _("%d Mb/s") % speed
- else:
- speed_str = ""
- self._set_device_info_value(dt, "speed", speed_str)
- # Hardware address
- hwaddr = dev_cfg.device and dev_cfg.device.get_hw_address()
- self._set_device_info_value(dt, "mac", hwaddr)
-
- def _refresh_device_type_page(self, dev_type):
- notebook = self.builder.get_object("notebook_types")
- if dev_type == NM.DeviceType.ETHERNET:
- notebook.set_current_page(0)
- self.builder.get_object("heading_wired_slaves").hide()
- self.builder.get_object("label_wired_slaves").hide()
- self.builder.get_object("heading_wired_vlanid").hide()
- self.builder.get_object("label_wired_vlanid").hide()
- self.builder.get_object("heading_wired_parent").hide()
- self.builder.get_object("label_wired_parent").hide()
- self.builder.get_object("remove_toolbutton").set_sensitive(False)
- elif dev_type in [NM.DeviceType.BOND,
- NM.DeviceType.TEAM,
- NM.DeviceType.BRIDGE]:
- notebook.set_current_page(0)
- self.builder.get_object("heading_wired_slaves").show()
- self.builder.get_object("label_wired_slaves").show()
- self.builder.get_object("heading_wired_vlanid").hide()
- self.builder.get_object("label_wired_vlanid").hide()
- self.builder.get_object("heading_wired_parent").hide()
- self.builder.get_object("label_wired_parent").hide()
- self.builder.get_object("remove_toolbutton").set_sensitive(True)
- elif dev_type == NM.DeviceType.VLAN:
- notebook.set_current_page(0)
- self.builder.get_object("heading_wired_slaves").hide()
- self.builder.get_object("label_wired_slaves").hide()
- self.builder.get_object("heading_wired_vlanid").show()
- self.builder.get_object("label_wired_vlanid").show()
- self.builder.get_object("heading_wired_parent").show()
- self.builder.get_object("label_wired_parent").show()
- self.builder.get_object("remove_toolbutton").set_sensitive(True)
- elif dev_type == NM.DeviceType.WIFI:
- notebook.set_current_page(1)
- self.builder.get_object("button_wireless_options").set_sensitive(self.selected_ap is not None)
-
- def _refresh_carrier_info(self):
- for i in self.dev_cfg_store:
- i[DEVICES_COLUMN_TITLE] = self._dev_title(i[DEVICES_COLUMN_OBJECT])
-
- def _refresh_header_ui(self, dev_cfg, state=None):
- if dev_cfg.get_device_type() in self.wired_ui_device_types:
- dev_type_str = "wired"
- elif dev_cfg.get_device_type() == NM.DeviceType.WIFI:
- dev_type_str = "wireless"
-
- if dev_type_str == "wired":
- # update icon according to device status
- img = self.builder.get_object("image_wired_device")
- img.set_from_icon_name(self._dev_icon_name(dev_cfg), Gtk.IconSize.DIALOG)
-
- # TODO: is this necessary? Isn't it static from glade?
- device_type_label = _(self.device_type_name.get(dev_cfg.get_device_type(), ""))
- self.builder.get_object("label_%s_device" % dev_type_str).set_label(
- "%s (%s)" % (device_type_label, dev_cfg.get_iface()))
-
- if state is None:
- if not dev_cfg.device:
- state = NM.DeviceState.DISCONNECTED
- else:
- state = dev_cfg.device.get_state()
-
- self.builder.get_object("label_%s_status" % dev_type_str).set_label(
- localized_string_of_device_state(dev_cfg.device, state))
-
- switch = self.builder.get_object("device_%s_off_switch" % dev_type_str)
- if dev_type_str == "wired":
- switch.set_visible(state not in (NM.DeviceState.UNAVAILABLE,
- NM.DeviceState.UNMANAGED))
- self._updating_device = True
- switch.set_active(state not in (NM.DeviceState.UNMANAGED,
- NM.DeviceState.UNAVAILABLE,
- NM.DeviceState.DISCONNECTED,
- NM.DeviceState.DEACTIVATING,
- NM.DeviceState.FAILED))
- self._updating_device = False
- elif dev_type_str == "wireless":
- self.on_wireless_enabled()
-
- def _set_device_info_value(self, dev_type_str, info, value_str):
- heading = self.builder.get_object("heading_%s_%s" % (dev_type_str, info))
- value_label = self.builder.get_object("label_%s_%s" % (dev_type_str, info))
- if value_str is None:
- really_hide(heading)
- really_hide(value_label)
- else:
- really_show(heading)
- really_show(value_label)
- value_label.set_label(value_str)
-
- def _add_ap(self, ap, active=False):
- ssid = ap.get_ssid()
- if not ssid:
- # get_ssid can return None if AP does not broadcast.
- return
- ssid = ssid.get_data()
- if not ssid:
- return
-
- mode = ap.get_mode()
- if not mode:
- return
-
- security = self._ap_security(ap)
-
- store = self.builder.get_object("liststore_wireless_network")
-
- # Decode the SSID (a byte sequence) into something resembling a string
- ssid_str = NM.utils_ssid_to_utf8(ssid)
-
- # the third column is for sorting
- itr = store.append([ap,
- ssid_str,
- ssid_str,
- ap.get_strength(),
- mode,
- security])
- if active:
- self.builder.get_object("combobox_wireless_network_name").set_active_iter(itr)
-
- def _get_strongest_unique_aps(self, access_points):
- strongest_aps = {}
- for ap in access_points:
- if not ap.get_ssid():
- # non-broadcasting AP. We don't do anything with these
- continue
- ssid = ap.get_ssid().get_data()
- if ssid in strongest_aps:
- if ap.get_strength() > strongest_aps[ssid].get_strength():
- strongest_aps[ssid] = ap
- else:
- strongest_aps[ssid] = ap
-
- return strongest_aps.values()
-
- def _ap_security(self, ap):
- ty = NM_AP_SEC_UNKNOWN
-
- flags = ap.get_flags()
- wpa_flags = ap.get_wpa_flags()
- rsn_flags = ap.get_rsn_flags()
-
- if (not (flags & NM._80211ApFlags.PRIVACY) and
- wpa_flags == NM._80211ApSecurityFlags.NONE and
- rsn_flags == NM._80211ApSecurityFlags.NONE):
- ty = NM_AP_SEC_NONE
- elif (flags & NM._80211ApFlags.PRIVACY and
- wpa_flags == NM._80211ApSecurityFlags.NONE and
- rsn_flags == NM._80211ApSecurityFlags.NONE):
- ty = NM_AP_SEC_WEP
- elif (not (flags & NM._80211ApFlags.PRIVACY) and
- wpa_flags != NM._80211ApSecurityFlags.NONE and
- rsn_flags != NM._80211ApSecurityFlags.NONE):
- ty = NM_AP_SEC_WPA
- else:
- ty = NM_AP_SEC_WPA2
-
- return ty
-
- def _ap_security_string(self, ap):
-
- flags = ap.get_flags()
- wpa_flags = ap.get_wpa_flags()
- rsn_flags = ap.get_rsn_flags()
-
- sec_str = ""
-
- if ((flags & NM._80211ApFlags.PRIVACY) and
- wpa_flags == NM._80211ApSecurityFlags.NONE and
- rsn_flags == NM._80211ApSecurityFlags.NONE):
- sec_str += "%s, " % _("WEP")
-
- if wpa_flags != NM._80211ApSecurityFlags.NONE:
- sec_str += "%s, " % _("WPA")
-
- if rsn_flags != NM._80211ApSecurityFlags.NONE:
- sec_str += "%s, " % _("WPA2")
-
- if ((wpa_flags & NM._80211ApSecurityFlags.KEY_MGMT_802_1X) or
- (rsn_flags & NM._80211ApSecurityFlags.KEY_MGMT_802_1X)):
- sec_str += "%s, " % _("Enterprise")
-
- if sec_str:
- sec_str = sec_str[:-2]
- else:
- sec_str = _("None")
-
- return sec_str
-
- def _ap_is_enterprise(self, ap):
- wpa_flags = ap.get_wpa_flags()
- rsn_flags = ap.get_rsn_flags()
- return ((wpa_flags & NM._80211ApSecurityFlags.KEY_MGMT_802_1X) or
- (rsn_flags & NM._80211ApSecurityFlags.KEY_MGMT_802_1X))
-
- @property
- def dev_cfgs(self):
- return [row[DEVICES_COLUMN_OBJECT] for
- row in self.dev_cfg_store]
-
- @property
- def hostname(self):
- return self.entry_hostname.get_text()
-
- @hostname.setter
- def hostname(self, value):
- if not value:
- return
- self.entry_hostname.set_text(value)
-
- @property
- def current_hostname(self):
- return self.label_current_hostname.get_text()
-
- @current_hostname.setter
- def current_hostname(self, value):
- if not value:
- return
- self.label_current_hostname.set_text(value)
-
- def disconnect_client_callbacks(self):
- for cb in [self.on_device_added, self.on_device_removed,
- self.on_connection_added, self.on_wireless_enabled,
- self.on_nm_state_changed]:
- _try_disconnect(self.client, cb)
-
- for device in self.client.get_devices():
- _try_disconnect(device, self.on_device_config_changed)
- _try_disconnect(device, self.on_device_state_changed)
- _try_disconnect(device, self.on_ip_obj_changed)
- for config in self._get_ip_configs(device):
- _try_disconnect(config, self.on_config_changed)
-
- def _get_ip_configs(self, device):
- out = []
- try:
- out.append(self.props.ip4_config)
- except AttributeError:
- pass
- try:
- out.append(self.props.ip6_config)
- except AttributeError:
- pass
-
- return out
-
-def _try_disconnect(obj, callback):
- try:
- obj.disconnect_by_func(callback)
- except TypeError as e:
- if not "nothing connected" in str(e):
- log.debug("network: %s", e)
-
-class SecretAgentDialog(GUIObject):
- builderObjects = ["secret_agent_dialog"]
- mainWidgetName = "secret_agent_dialog"
- uiFile = "spokes/network.glade"
-
- def __init__(self, *args, **kwargs):
- self._content = kwargs.pop('content', {})
- GUIObject.__init__(self, *args, **kwargs)
- self.builder.get_object("label_message").set_text(self._content['message'])
- self._connect_button = self.builder.get_object("connect_button")
-
- def initialize(self):
- self._entries = {}
- grid = Gtk.Grid()
- grid.set_row_spacing(6)
- grid.set_column_spacing(6)
-
- for row, secret in enumerate(self._content['secrets']):
- label = Gtk.Label(label=secret['label'], halign=Gtk.Align.START)
- entry = Gtk.Entry(hexpand=True)
- entry.set_text(secret['value'])
- if secret['key']:
- self._entries[secret['key']] = entry
- else:
- entry.set_sensitive(False)
- if secret['password']:
- entry.set_visibility(False)
- self._validate(entry, secret)
- entry.connect("changed", self._validate, secret)
- entry.connect("activate", self._password_entered_cb)
- label.set_use_underline(True)
- label.set_mnemonic_widget(entry)
- grid.attach(label, 0, row, 1, 1)
- grid.attach(entry, 1, row, 1, 1)
-
- self.builder.get_object("password_box").add(grid)
-
- def run(self):
- self.initialize()
- self.window.show_all()
- rc = self.window.run()
- for secret in self._content['secrets']:
- if secret['key']:
- secret['value'] = self._entries[secret['key']].get_text()
- self.window.destroy()
- return rc
-
- @property
- def valid(self):
- return all(secret.get('valid', False) for secret in self._content['secrets'])
-
- def _validate(self, entry, secret):
- secret['value'] = entry.get_text()
- if secret['validate']:
- secret['valid'] = secret['validate'](secret)
- else:
- secret['valid'] = len(secret['value']) > 0
- self._update_connect_button()
-
- def _password_entered_cb(self, entry):
- if self._connect_button.get_sensitive() and self.valid:
- self.window.response(1)
-
- def _update_connect_button(self):
- self._connect_button.set_sensitive(self.valid)
-
-secret_agent = None
-
-class NotAuthorizedException(dbus.DBusException):
- _dbus_error_name = SECRET_AGENT_IFACE + '.NotAuthorized'
-
-class SecretAgent(dbus.service.Object):
- def __init__(self, spoke):
- self._bus = dbus.SystemBus()
- self.spoke = spoke
- dbus.service.Object.__init__(self, self._bus, "/org/freedesktop/NetworkManager/SecretAgent")
-
- @dbus.service.method(SECRET_AGENT_IFACE,
- in_signature='a{sa{sv}}osasb',
- out_signature='a{sa{sv}}',
- sender_keyword='sender')
- def GetSecrets(self, connection_hash, connection_path, setting_name, hints, flags, sender=None):
- if not sender:
- raise NotAuthorizedException("Internal error: couldn't get sender")
- uid = self._bus.get_unix_user(sender)
- if uid != 0:
- raise NotAuthorizedException("UID %d not authorized" % uid)
-
- log.debug("network: secrets requested path '%s' setting '%s' hints '%s' new %d",
- connection_path, setting_name, str(hints), flags)
- if not (flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION):
- return
-
- content = self._get_content(setting_name, connection_hash)
- dialog = SecretAgentDialog(self.spoke.data, content=content)
- with self.spoke.main_window.enlightbox(dialog.window):
- rc = dialog.run()
-
- secrets = dbus.Dictionary()
- if rc == 1:
- for secret in content['secrets']:
- if secret['key']:
- secrets[secret['key']] = secret['value']
-
- settings = dbus.Dictionary({setting_name: secrets})
-
- return settings
-
- def _get_content(self, setting_name, connection_hash):
- content = {}
- connection_type = connection_hash['connection']['type']
- if connection_type == "802-11-wireless":
- content['title'] = _("Authentication required by wireless network")
- content['message'] = _("Passwords or encryption keys are required to access\n"
- "the wireless network '%(network_id)s'.") \
- % {'network_id':str(connection_hash['connection']['id'])}
- content['secrets'] = self._get_wireless_secrets(setting_name, connection_hash)
- else:
- log.info("Connection type %s not supported by secret agent", connection_type)
-
- return content
-
- def _get_wireless_secrets(self, setting_name, connection_hash):
- key_mgmt = connection_hash['802-11-wireless-security']['key-mgmt']
- original_secrets = connection_hash[setting_name]
- secrets = []
- if key_mgmt in ['wpa-none', 'wpa-psk']:
- secrets.append({'label' : C_('GUI|Network|Secrets Dialog', '_Password:'),
- 'key' : 'psk',
- 'value' : original_secrets.get('psk', ''),
- 'validate' : self._validate_wpapsk,
- 'password' : True})
- # static WEP
- elif key_mgmt == 'none':
- key_idx = str(original_secrets.get('wep_tx_keyidx', '0'))
- secrets.append({'label' : C_('GUI|Network|Secrets Dialog', '_Key:'),
- 'key' : 'wep-key%s' % key_idx,
- 'value' : original_secrets.get('wep-key%s' % key_idx, ''),
- 'wep_key_type': original_secrets.get('wep-key-type', ''),
- 'validate' : self._validate_staticwep,
- 'password' : True})
- # WPA-Enterprise
- elif key_mgmt == 'wpa-eap':
- eap = original_secrets['eap'][0]
- if eap in ('md5', 'leap', 'ttls', 'peap'):
- secrets.append({'label' : _('User name: '),
- 'key' : None,
- 'value' : original_secrets.get('identity', ''),
- 'validate' : None,
- 'password' : False})
- secrets.append({'label' : _('Password: '),
- 'key' : 'password',
- 'value' : original_secrets.get('password', ''),
- 'validate' : None,
- 'password' : True})
- elif eap == 'tls':
- secrets.append({'label' : _('Identity: '),
- 'key' : None,
- 'value' : original_secrets.get('identity', ''),
- 'validate' : None,
- 'password' : False})
- secrets.append({'label' : _('Private key password: '),
- 'key' : 'private-key-password',
- 'value' : original_secrets.get('private-key-password', ''),
- 'validate' : None,
- 'password' : True})
- else:
- log.info("Unsupported wireless key management: %s", key_mgmt)
-
- return secrets
-
- def _validate_wpapsk(self, secret):
- value = secret['value']
- if len(value) == 64:
- # must be composed of hexadecimal digits only
- return all(c in string.hexdigits for c in value)
- else:
- return 8 <= len(value) <= 63
-
- def _validate_staticwep(self, secret):
- value = secret['value']
- if secret['wep_key_type'] == NM.WepKeyType.KEY:
- if len(value) in (10, 26):
- return all(c in string.hexdigits for c in value)
- elif len(value) in (5, 13):
- return all(c in string.ascii_letters for c in value)
- else:
- return False
- elif secret['wep_key_type'] == NM.WepKeyType.PASSPHRASE:
- return 0 <= len(value) <= 64
- else:
- return True
-
-def register_secret_agent(spoke):
-
- if not can_touch_runtime_system("register anaconda secret agent"):
- return False
-
- global secret_agent
- if not secret_agent:
- # Ignore an error from pylint incorrectly analyzing types in dbus-python
- secret_agent = SecretAgent(spoke) # pylint: disable=no-value-for-parameter
- bus = dbus.SystemBus()
- proxy = bus.get_object(NM_SERVICE, AGENT_MANAGER_PATH)
- proxy.Register("anaconda", dbus_interface=AGENT_MANAGER_IFACE)
- else:
- secret_agent.spoke = spoke
-
- return True
-
-
-class NetworkSpoke(FirstbootSpokeMixIn, NormalSpoke):
- """
- .. inheritance-diagram:: NetworkSpoke
- :parts: 3
- """
- builderObjects = ["networkWindow", "liststore_wireless_network", "liststore_devices", "add_device_dialog", "liststore_add_device"]
- mainWidgetName = "networkWindow"
- uiFile = "spokes/network.glade"
- helpFile = "NetworkSpoke.xml"
-
- title = CN_("GUI|Spoke", "_NETWORK & HOST NAME")
- icon = "network-transmit-receive-symbolic"
-
- category = SystemCategory
-
- def __init__(self, *args, **kwargs):
- NormalSpoke.__init__(self, *args, **kwargs)
- self.networking_changed = False
- self.network_control_box = NetworkControlBox(self.builder, nmclient, spoke=self)
- self.network_control_box.hostname = self.data.network.hostname
- self.network_control_box.current_hostname = network.current_hostname()
- self.network_control_box.connect("nm-state-changed",
- self.on_nm_state_changed)
- self.network_control_box.connect("device-state-changed",
- self.on_device_state_changed)
- self.network_control_box.connect("apply-hostname",
- self.on_apply_hostname)
-
- def apply(self):
- _update_network_data(self.data, self.network_control_box)
- log.debug("network: apply ksdata %s", self.data.network)
-
- # if installation media or hdd aren't used and settings have changed
- # try if source is available
- if self.networking_changed:
- if ANACONDA_ENVIRON in anaconda_flags.environs and self.payload.needsNetwork:
- log.debug("network spoke (apply) refresh payload")
- from pyanaconda.packaging import payloadMgr
- payloadMgr.restartThread(self.storage, self.data, self.payload, self.instclass,
- fallback=not anaconda_flags.automatedInstall)
- else:
- log.debug("network spoke (apply), payload refresh skipped (running outside of installation environment)")
- self.networking_changed = False
- else:
- log.debug("network spoke (apply), no changes detected")
- self.network_control_box.kill_nmce(msg="leaving network spoke")
-
- @property
- def completed(self):
- # TODO: check also if source requires updates when implemented
- return (not can_touch_runtime_system("require network connection")
- or nm.nm_activated_devices())
-
- @property
- def mandatory(self):
- # the network spoke should be mandatory only if it is running
- # during the installation and if the installation source requires network
- return ANACONDA_ENVIRON in anaconda_flags.environs and self.payload.needsNetwork
-
- @property
- def status(self):
- """ A short string describing which devices are connected. """
- return network.status_message()
-
- def initialize(self):
- register_secret_agent(self)
- NormalSpoke.initialize(self)
- self.network_control_box.initialize()
- if not can_touch_runtime_system("hide hint to use network configuration in DE"):
- self.builder.get_object("network_config_vbox").set_no_show_all(True)
- self.builder.get_object("network_config_vbox").hide()
- else:
- self.builder.get_object("live_hint_label").set_no_show_all(True)
- self.builder.get_object("live_hint_label").hide()
-
- if not self.data.network.seen:
- _update_network_data(self.data, self.network_control_box)
-
- def refresh(self):
- NormalSpoke.refresh(self)
- self.network_control_box.refresh()
- self.network_control_box.current_hostname = network.current_hostname()
-
- def on_nm_state_changed(self, *args):
- gtk_call_once(self._update_status)
- gtk_call_once(self._update_hostname)
-
- def on_device_state_changed(self, source, device, new_state, *args):
- if new_state in (NM.DeviceState.ACTIVATED,
- NM.DeviceState.DISCONNECTED,
- NM.DeviceState.UNAVAILABLE):
- gtk_call_once(self._update_status)
-
- def on_apply_hostname(self, *args):
- hostname = self.network_control_box.hostname
- (valid, error) = network.sanityCheckHostname(hostname)
- if not valid:
- self.clear_info()
- msg = _("Host name is not valid: %s") % error
- self.set_warning(msg)
- self.network_control_box.entry_hostname.grab_focus()
- else:
- self.clear_info()
- network.set_hostname(hostname)
- self._update_hostname()
-
- def _update_status(self):
- hubQ.send_message(self.__class__.__name__, self.status)
-
- def _update_hostname(self):
- self.network_control_box.current_hostname = network.current_hostname()
-
- def on_back_clicked(self, button):
- hostname = self.network_control_box.hostname
- (valid, error) = network.sanityCheckHostname(hostname)
- if not valid:
- self.clear_info()
- msg = _("Host name is not valid: %s") % error
- self.set_warning(msg)
- self.network_control_box.entry_hostname.grab_focus()
- else:
- self.clear_info()
- NormalSpoke.on_back_clicked(self, button)
-
- def finished(self):
- """Disconnect callbacks
-
- Called when leaving summary hub
- """
- self.network_control_box.kill_nmce(msg="finished with network spoke")
- self.network_control_box.disconnect_client_callbacks()
-
-class NetworkStandaloneSpoke(StandaloneSpoke):
- """
- .. inheritance-diagram:: NetworkStandaloneSpoke
- :parts: 3
- """
- builderObjects = ["networkStandaloneWindow", "networkControlBox_vbox", "liststore_wireless_network", "liststore_devices", "add_device_dialog", "liststore_add_device"]
- mainWidgetName = "networkStandaloneWindow"
- uiFile = "spokes/network.glade"
-
- preForHub = SummaryHub
- priority = 10
-
- def __init__(self, *args, **kwargs):
- StandaloneSpoke.__init__(self, *args, **kwargs)
- self.network_control_box = NetworkControlBox(self.builder, nmclient, spoke=self)
- self.network_control_box.hostname = self.data.network.hostname
- self.network_control_box.current_hostname = network.current_hostname()
- parent = self.builder.get_object("AnacondaStandaloneWindow-action_area5")
- parent.add(self.network_control_box.vbox)
-
- self.network_control_box.connect("nm-state-changed",
- self.on_nm_state_changed)
- self.network_control_box.connect("apply-hostname",
- self.on_apply_hostname)
-
- self._initially_available = self.completed
- log.debug("network standalone spoke (init): completed: %s", self._initially_available)
- self._now_available = False
-
- def apply(self):
- _update_network_data(self.data, self.network_control_box)
-
- log.debug("network: apply ksdata %s", self.data.network)
-
- self._now_available = self.completed
-
- log.debug("network standalone spoke (apply) payload: %s completed: %s", self.payload.baseRepo, self._now_available)
- if (not self.payload.baseRepo and not self._initially_available
- and self._now_available and self.payload.needsNetwork):
- from pyanaconda.packaging import payloadMgr
- payloadMgr.restartThread(self.storage, self.data, self.payload, self.instclass,
- fallback=not anaconda_flags.automatedInstall)
-
- self.network_control_box.kill_nmce(msg="leaving standalone network spoke")
- self.network_control_box.disconnect_client_callbacks()
-
- @property
- def completed(self):
- return (not can_touch_runtime_system("require network connection")
- or nm.nm_activated_devices()
- or self.data.method.method not in ("url", "nfs"))
-
- def initialize(self):
- register_secret_agent(self)
- StandaloneSpoke.initialize(self)
- self.network_control_box.initialize()
-
- def refresh(self):
- StandaloneSpoke.refresh(self)
- self.network_control_box.refresh()
- self.network_control_box.current_hostname = network.current_hostname()
-
- def _on_continue_clicked(self, window, user_data=None):
- hostname = self.network_control_box.hostname
- (valid, error) = network.sanityCheckHostname(hostname)
- if not valid:
- self.clear_info()
- msg = _("Host name is not valid: %s") % error
- self.set_warning(msg)
- self.network_control_box.entry_hostname.grab_focus()
- else:
- self.clear_info()
- StandaloneSpoke._on_continue_clicked(self, window, user_data)
-
- # Use case: slow dhcp has connected when on spoke
- def on_nm_state_changed(self, *args):
- gtk_call_once(self._update_hostname)
-
- def on_apply_hostname(self, *args):
- hostname = self.network_control_box.hostname
- (valid, error) = network.sanityCheckHostname(hostname)
- if not valid:
- self.clear_info()
- msg = _("Host name is not valid: %s") % error
- self.set_warning(msg)
- self.network_control_box.entry_hostname.grab_focus()
- else:
- self.clear_info()
- network.set_hostname(hostname)
- self._update_hostname()
-
- def _update_hostname(self):
- self.network_control_box.current_hostname = network.current_hostname()
-
-def _update_network_data(data, ncb):
- data.network.network = []
- for i, dev_cfg in enumerate(ncb.dev_cfgs):
- devname = dev_cfg.get_iface()
- nd = network.ksdata_from_ifcfg(devname, dev_cfg.get_uuid())
- if not nd:
- continue
- if devname in nm.nm_activated_devices():
- nd.activate = True
- else:
- # First network command defaults to --activate so we must
- # use --no-activate explicitly to prevent the default
- if i == 0:
- nd.activate = False
-
- data.network.network.append(nd)
- hostname = ncb.hostname
- network.update_hostname_data(data, hostname)
-
-
-def test():
- win = Gtk.Window()
- win.connect("delete-event", Gtk.main_quit)
-
- builder = Gtk.Builder()
- import os
- ui_file_path = os.environ.get('UIPATH')+'spokes/network.glade'
- builder.add_from_file(ui_file_path)
-
- n = NetworkControlBox(builder, nmclient)
- n.initialize()
- n.refresh()
-
- n.vbox.reparent(win)
-
- win.show_all()
- Gtk.main()
-
-if __name__ == "__main__":
- test()
--
2.14.4