1198 lines
46 KiB
Python
1198 lines
46 KiB
Python
# 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.
|
|
#
|
|
# Red Hat Author(s): Radek Vykydal <rvykydal@redhat.com>
|
|
#
|
|
|
|
# TODO:
|
|
|
|
# - move callback connection to initialize?
|
|
# - Automatically reconnecting wifi after failure
|
|
# https://bugzilla.redhat.com/show_bug.cgi?id=712778#c1
|
|
# - secrets agent - use nm_applet?
|
|
# see we_dont_have_nm_applet_as_secrets_agent
|
|
# - callback on NM_CLIENT_ACTIVE_CONNECTIONS
|
|
# - support connection to hidden network (ap-other)
|
|
# - device_is_stored
|
|
# - NMClient.CLIENT_WIRELESS_ENABLED callback (hw switch?) - test
|
|
# - nm-c-e run: blocking? logging?
|
|
|
|
from gi.repository import Gtk, AnacondaWidgets
|
|
|
|
from pyanaconda.flags import flags
|
|
from pyanaconda.ui.gui import GUIObject, communication
|
|
from pyanaconda.ui.gui.spokes import NormalSpoke, StandaloneSpoke
|
|
from pyanaconda.ui.gui.categories.software import SoftwareCategory
|
|
from pyanaconda.ui.gui.hubs.summary import SummaryHub
|
|
from pyanaconda.ui.gui.utils import gtk_call_once
|
|
|
|
from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, getActiveNetDevs, logIfcfgFiles, update_hostname, sanityCheckHostname
|
|
|
|
from gi.repository import GLib, GObject, Pango, Gio, NetworkManager, NMClient
|
|
import dbus
|
|
import socket
|
|
import subprocess
|
|
import struct
|
|
import time
|
|
from dbus.mainloop.glib import DBusGMainLoop
|
|
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
|
|
|
import ctypes
|
|
ctypes.cdll.LoadLibrary("libnm-util.so.2")
|
|
nm_utils = ctypes.CDLL("libnm-util.so.2")
|
|
|
|
import gettext
|
|
_ = lambda x: gettext.ldgettext("anaconda", x)
|
|
N_ = lambda x: x
|
|
P_ = lambda x, y, z: gettext.ldngettext("anaconda", x, y, z)
|
|
|
|
import logging
|
|
log = logging.getLogger("anaconda")
|
|
|
|
# These are required for dbus API use we need because of
|
|
# NM_GI_BUGS: 767998, 773678
|
|
NM_SERVICE = "org.freedesktop.NetworkManager"
|
|
NM_MANAGER_PATH = "/org/freedesktop/NetworkManager"
|
|
NM_SETTINGS_PATH = "/org/freedesktop/NetworkManager/Settings"
|
|
NM_MANAGER_IFACE = "org.freedesktop.NetworkManager"
|
|
NM_SETTINGS_IFACE = "org.freedesktop.NetworkManager.Settings"
|
|
NM_CONNECTION_IFACE = "org.freedesktop.NetworkManager.Settings.Connection"
|
|
NM_DEVICE_IFACE = "org.freedesktop.NetworkManager.Device"
|
|
NM_802_11_AP_FLAGS_PRIVACY = 0x1
|
|
NM_802_11_AP_SEC_NONE = 0x0
|
|
NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x200
|
|
DBUS_PROPS_IFACE = "org.freedesktop.DBus.Properties"
|
|
|
|
def getNMObjProperty(object, nm_iface_suffix, property):
|
|
props_iface = dbus.Interface(object, DBUS_PROPS_IFACE)
|
|
return props_iface.Get("org.freedesktop.NetworkManager"+nm_iface_suffix,
|
|
property)
|
|
|
|
|
|
DEVICES_COLUMN_TITLE = 2
|
|
DEVICES_COLUMN_OBJECT = 3
|
|
|
|
|
|
def localized_string_of_device_state(device):
|
|
str = _("Status unknown (missing)")
|
|
|
|
state = device.get_state()
|
|
if state == NetworkManager.DeviceState.UNKNOWN:
|
|
str = _("Status unknown")
|
|
elif state == NetworkManager.DeviceState.UNMANAGED:
|
|
str = _("Unmanaged")
|
|
elif state == NetworkManager.DeviceState.UNAVAILABLE:
|
|
if device.get_firmware_missing():
|
|
str = _("Firmware missing")
|
|
elif (device.get_device_type() == NetworkManager.DeviceType.ETHERNET
|
|
and not device.get_carrier()):
|
|
str = _("Cable unplugged")
|
|
else:
|
|
str = _("Unavailable")
|
|
elif state == NetworkManager.DeviceState.DISCONNECTED:
|
|
str = _("Disconnected")
|
|
elif state in (NetworkManager.DeviceState.PREPARE,
|
|
NetworkManager.DeviceState.CONFIG,
|
|
NetworkManager.DeviceState.IP_CONFIG,
|
|
NetworkManager.DeviceState.IP_CHECK):
|
|
str = _("Connecting")
|
|
elif state == NetworkManager.DeviceState.NEED_AUTH:
|
|
str = _("Authentication required")
|
|
elif state == NetworkManager.DeviceState.ACTIVATED:
|
|
str = _("Connected")
|
|
elif state == NetworkManager.DeviceState.DEACTIVATING:
|
|
str = _("Disconnecting")
|
|
elif state == NetworkManager.DeviceState.FAILED:
|
|
str = _("Connection failed")
|
|
|
|
return str
|
|
|
|
configuration_of_disconnected_devices_allowed = True
|
|
# it is not in gnome-control-center but it makes sense
|
|
# for installer
|
|
# https://bugzilla.redhat.com/show_bug.cgi?id=704119
|
|
|
|
we_dont_have_nm_applet_as_secrets_agent = True
|
|
# so we have to disconnect from former ap before trying
|
|
# to connect to new one bound to fail due to no secrets
|
|
|
|
__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, property):
|
|
if property.name == 'signal':
|
|
return self.signal
|
|
else:
|
|
raise AttributeError, 'unknown property %s' % property.name
|
|
|
|
def do_set_property(self, property, value):
|
|
if property.name == 'signal':
|
|
self.signal = value
|
|
self._set_icon_name(value)
|
|
else:
|
|
raise AttributeError, 'unknown property %s' % property.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, property):
|
|
if property.name == 'security':
|
|
return self.security
|
|
else:
|
|
raise AttributeError, 'unknown property %s' % property.name
|
|
|
|
def do_set_property(self, property, value):
|
|
if property.name == 'security':
|
|
self.security = value
|
|
self._set_icon_name(value)
|
|
else:
|
|
raise AttributeError, 'unknown property %s' % property.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 NetworkControlBox(object):
|
|
|
|
supported_device_types = [
|
|
NetworkManager.DeviceType.ETHERNET,
|
|
NetworkManager.DeviceType.WIFI,
|
|
]
|
|
|
|
def __init__(self, builder):
|
|
|
|
self.builder = builder
|
|
|
|
# these buttons are only for vpn and proxy
|
|
self.builder.get_object("add_toolbutton").set_sensitive(False)
|
|
self.builder.get_object("remove_toolbutton").set_sensitive(False)
|
|
|
|
not_supported = ["start_hotspot_button",
|
|
"stop_hotspot_button",
|
|
"heading_hotspot_network_name",
|
|
"heading_hotspot_security_key",
|
|
"label_hotspot_network_name",
|
|
"label_hotspot_security_key",
|
|
"devices_toolbar",
|
|
"hbox54",
|
|
]
|
|
|
|
do_not_show_in_refresh = ["heading_wireless_network_name",
|
|
"combobox_wireless_network_name"]
|
|
do_not_show_in_refresh += ["%s_%s_%s" % (widget, type, value)
|
|
for widget in ["heading", "label"]
|
|
for type in ["wired", "wireless"]
|
|
for value in ["ipv4", "ipv6", "dns", "route"]]
|
|
do_not_show_in_refresh += ["%s_wired_subnet" % widget
|
|
for widget in ["heading", "label"]]
|
|
|
|
for id in not_supported + do_not_show_in_refresh:
|
|
self.builder.get_object(id).set_no_show_all(True)
|
|
self.builder.get_object(id).hide()
|
|
|
|
self.builder.get_object("notebook_types").set_show_tabs(False)
|
|
|
|
# to prevent UI update signals races
|
|
self._updating_device = False
|
|
|
|
self.client = NMClient.Client.new()
|
|
self.remote_settings = NMClient.RemoteSettings()
|
|
|
|
# devices list
|
|
# limited to wired and wireless
|
|
treeview = self.builder.get_object("treeview_devices")
|
|
self._add_device_columns(treeview)
|
|
devices_store = self.builder.get_object("liststore_devices")
|
|
devices_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_ssid = None
|
|
|
|
# NM Client
|
|
self.client.connect("device-added", self.on_device_added)
|
|
self.client.connect("device-removed", self.on_device_removed)
|
|
|
|
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.client.connect("notify::%s" % NMClient.CLIENT_WIRELESS_ENABLED,
|
|
self.on_wireless_enabled)
|
|
|
|
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")
|
|
|
|
|
|
@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 initialize(self):
|
|
for device in self.client.get_devices():
|
|
self.add_device(device)
|
|
|
|
treeview = self.builder.get_object("treeview_devices")
|
|
devices_store = self.builder.get_object("liststore_devices")
|
|
selection = treeview.get_selection()
|
|
itr = devices_store.get_iter_first()
|
|
if itr:
|
|
selection.select_iter(itr)
|
|
|
|
def refresh(self):
|
|
device = self.selected_device()
|
|
self.refresh_ui(device)
|
|
|
|
def activated_connections(self):
|
|
"""Returns list of tuples (device_name, ssid), ssid is None for wired."""
|
|
active_devs = []
|
|
|
|
for con in self.client.get_active_connections():
|
|
if con.get_state() != NetworkManager.ActiveConnectionState.ACTIVATED:
|
|
continue
|
|
device = con.get_devices()[0]
|
|
if device.get_device_type() == NetworkManager.DeviceType.ETHERNET:
|
|
active_devs.append((device.get_iface(), None))
|
|
elif device.get_device_type() == NetworkManager.DeviceType.WIFI:
|
|
active_devs.append((device.get_iface(),
|
|
device.get_active_access_point().get_ssid()))
|
|
return active_devs
|
|
|
|
# Signal handlers.
|
|
def on_device_selection_changed(self, *args):
|
|
device = self.selected_device()
|
|
log.debug("network: selected device %s" % device.get_iface())
|
|
self.refresh_ui(device)
|
|
|
|
def on_device_state_changed(self, *args):
|
|
device = args[0]
|
|
new_state = args[1]
|
|
if new_state == NetworkManager.DeviceState.SECONDARIES:
|
|
return
|
|
self._refresh_carrier_info()
|
|
read_config_values = (new_state == NetworkManager.DeviceState.ACTIVATED)
|
|
if device == self.selected_device():
|
|
self.refresh_ui(device, read_config_values, new_state)
|
|
|
|
def on_wireless_ap_changed_cb(self, combobox, *args):
|
|
if self._updating_device:
|
|
return
|
|
iter = combobox.get_active_iter()
|
|
if not iter:
|
|
return
|
|
|
|
device = self.selected_device()
|
|
ap_obj_path, ssid_target = combobox.get_model().get(iter, 0, 1)
|
|
self.selected_ssid = ssid_target
|
|
if ap_obj_path == "ap-other...":
|
|
return
|
|
|
|
log.info("network: access point changed: %s" % ssid_target)
|
|
|
|
if we_dont_have_nm_applet_as_secrets_agent:
|
|
if self.find_active_connection_for_device(device):
|
|
# TODO we should pass callback and block until really disconnected?
|
|
# or is wireless reconnection stuff solved in NM? TEST!
|
|
device.disconnect(None, None)
|
|
|
|
con = self.find_connection_for_device(device, ssid_target)
|
|
if con:
|
|
self.client.activate_connection(con, device,
|
|
None, None, None)
|
|
else:
|
|
self.client.add_and_activate_connection(None, device, ap_obj_path,
|
|
None, None)
|
|
|
|
def on_device_added(self, client, device, *args):
|
|
self.add_device(device)
|
|
|
|
def on_device_removed(self, client, device, *args):
|
|
self.remove_device(device)
|
|
|
|
def on_edit_connection(self, *args):
|
|
device = self.selected_device()
|
|
if not device:
|
|
return
|
|
|
|
con = self.find_active_connection_for_device(device)
|
|
ssid = None
|
|
if not con and configuration_of_disconnected_devices_allowed:
|
|
if device.get_device_type() == NetworkManager.DeviceType.WIFI:
|
|
ssid = self.selected_ssid
|
|
con = self.find_connection_for_device(device, ssid)
|
|
|
|
if con:
|
|
uuid = con.get_uuid()
|
|
else:
|
|
return
|
|
|
|
# 871132 auto activate wireless connection after editing if it is not
|
|
# already activated (assume entering secrets)
|
|
activate = None
|
|
if (device.get_device_type() == NetworkManager.DeviceType.WIFI
|
|
and ssid and (device.get_iface(), ssid) not in self.activated_connections()):
|
|
activate = (con, device)
|
|
|
|
log.info("network: configuring connection %s device %s ssid %s" % (uuid, device.get_iface(), ssid))
|
|
self.builder.get_object("button_wired_options").set_sensitive(False)
|
|
proc = subprocess.Popen(["nm-connection-editor", "--edit", "%s" % uuid])
|
|
|
|
GLib.child_watch_add(proc.pid, self.on_nmce_exited, activate)
|
|
|
|
def on_nmce_exited(self, pid, condition, activate):
|
|
self.builder.get_object("button_wired_options").set_sensitive(True)
|
|
if activate:
|
|
con, device = activate
|
|
gtk_call_once(self._activate_connection_cb, con, device)
|
|
logIfcfgFiles("nm-c-e run")
|
|
|
|
def _activate_connection_cb(self, con, device):
|
|
self.client.activate_connection(con, device,
|
|
None, None, None)
|
|
|
|
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()
|
|
device = self.selected_device()
|
|
|
|
log.info("network: device %s switched %s" %
|
|
(device.get_iface(), "on" if active else "off"))
|
|
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
if active:
|
|
cons = self.remote_settings.list_connections()
|
|
dev_cons = device.filter_connections(cons)
|
|
if dev_cons:
|
|
self.client.activate_connection(dev_cons[0], device,
|
|
None, None, None)
|
|
else:
|
|
self.client.add_and_activate_connection(None, device, None,
|
|
None, None)
|
|
else:
|
|
device.disconnect(None, None)
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
self.client.wireless_set_enabled(active)
|
|
|
|
def selected_device(self):
|
|
selection = self.builder.get_object("treeview_devices").get_selection()
|
|
(model, iter) = selection.get_selected()
|
|
if not iter:
|
|
return None
|
|
return model.get(iter, DEVICES_COLUMN_OBJECT)[0]
|
|
|
|
def find_connection_for_device(self, device, ssid=None):
|
|
dev_hwaddr = device.get_hw_address()
|
|
cons = self.remote_settings.list_connections()
|
|
for con in cons:
|
|
con_type = con.get_setting_connection().get_connection_type()
|
|
if con_type == NetworkManager.SETTING_WIRED_SETTING_NAME:
|
|
settings = con.get_setting_wired()
|
|
elif con_type == NetworkManager.SETTING_WIRELESS_SETTING_NAME:
|
|
settings = con.get_setting_wireless()
|
|
if ssid and ssid != settings.get_ssid():
|
|
continue
|
|
else:
|
|
continue
|
|
con_hwaddr = ":".join("%02X" % ord(bytechar) for bytechar in settings.get_mac_address())
|
|
if con_hwaddr == dev_hwaddr:
|
|
return con
|
|
return None
|
|
|
|
def find_active_connection_for_device(self, device):
|
|
cons = self.client.get_active_connections()
|
|
for con in cons:
|
|
if con.get_devices()[0] is device:
|
|
return self.remote_settings.get_connection_by_path(con.get_connection())
|
|
return None
|
|
|
|
def _device_is_stored(self, nm_device):
|
|
"""TODO check that device with Udi of nm_device is already in
|
|
liststore"""
|
|
return False
|
|
|
|
def add_device(self, device):
|
|
if self._device_is_stored(device):
|
|
return
|
|
|
|
if device.get_device_type() not in self.supported_device_types:
|
|
return
|
|
|
|
device.connect("state-changed", self.on_device_state_changed)
|
|
|
|
self.builder.get_object("liststore_devices").append([
|
|
self._dev_icon_name(device),
|
|
self._dev_type_sort_value(device),
|
|
self._dev_title(device),
|
|
device,
|
|
])
|
|
|
|
def _dev_icon_name(self, device):
|
|
icon_name = ""
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
if device.get_state() == NetworkManager.DeviceState.UNAVAILABLE:
|
|
icon_name = "network-wired-disconnected"
|
|
else:
|
|
icon_name = "network-wired"
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
icon_name = "network-wireless"
|
|
|
|
return icon_name
|
|
|
|
def _dev_type_sort_value(self, device):
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
str = "1"
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
str = "2"
|
|
else:
|
|
str = "3"
|
|
return str
|
|
|
|
def _dev_title(self, device):
|
|
unplugged = ''
|
|
if (device.get_state() == NetworkManager.DeviceState.UNAVAILABLE
|
|
and device.get_device_type() == NetworkManager.DeviceType.ETHERNET
|
|
and not device.get_carrier()):
|
|
# Translators: ethernet cable is unplugged
|
|
unplugged = ', <i>%s</i>' % _("unplugged")
|
|
title = '<span size="large">%s (%s%s)</span>' % (self._dev_type_str(device),
|
|
device.get_iface(),
|
|
unplugged)
|
|
title += '\n<span size="small">%s %s</span>' % (device.get_vendor() or "",
|
|
device.get_product() or "")
|
|
return title
|
|
|
|
def _dev_type_str(self, device):
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.UNKNOWN:
|
|
title = _("Unknown")
|
|
elif dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
title = _("Ethernet")
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
title = _("Wireless")
|
|
else:
|
|
title = ""
|
|
return title
|
|
|
|
def remove_device(self, device):
|
|
# This should not concern wifi and ethernet devices,
|
|
# just virtual devices e.g. vpn probably
|
|
# TODO test!, remove perhaps
|
|
model = self.builder.get_object("liststore_devices")
|
|
rows_to_remove = []
|
|
for row in model:
|
|
if (device.get_udi() == row[DEVICES_COLUMN_OBJECT].get_udi()):
|
|
rows_to_remove.append(row)
|
|
for row in rows_to_remove:
|
|
del(row)
|
|
|
|
def refresh_ui(self, device, read_config_values=True, state=None):
|
|
|
|
if not device:
|
|
notebook = self.builder.get_object("notebook_types")
|
|
notebook.set_current_page(5)
|
|
return
|
|
|
|
self._refresh_device_type_page(device)
|
|
self._refresh_header_ui(device, state)
|
|
self._refresh_speed_hwaddr(device, state)
|
|
self._refresh_ap(device, state)
|
|
if read_config_values:
|
|
num_of_tries = 3
|
|
else:
|
|
num_of_tries = 0
|
|
self._refresh_device_cfg((device, num_of_tries), state)
|
|
|
|
def _refresh_device_cfg(self, dev_tries, state):
|
|
device, num_of_tries = dev_tries
|
|
ipv4cfg = None
|
|
ipv6cfg = None
|
|
|
|
# We might need to wait for config objects to become available
|
|
if num_of_tries > 0:
|
|
ipv4cfg = device.get_ip4_config()
|
|
ipv6cfg = device.get_ip6_config()
|
|
if not ipv4cfg and not ipv6cfg:
|
|
GLib.timeout_add(300,
|
|
self._refresh_device_cfg,
|
|
(device, num_of_tries-1),
|
|
state)
|
|
return False
|
|
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
dt = "wired"
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
dt = "wireless"
|
|
|
|
if state is None:
|
|
state = device.get_state()
|
|
if (ipv4cfg
|
|
and state == NetworkManager.DeviceState.ACTIVATED):
|
|
addr = socket.inet_ntoa(struct.pack('=L',
|
|
ipv4cfg.get_addresses()[0].get_address()))
|
|
self._set_device_info_value(dt, "ipv4", addr)
|
|
dnss = " ".join([socket.inet_ntoa(struct.pack('=L', addr))
|
|
for addr in ipv4cfg.get_nameservers()])
|
|
self._set_device_info_value(dt, "dns", dnss)
|
|
gateway = socket.inet_ntoa(struct.pack('=L',
|
|
ipv4cfg.get_addresses()[0].get_gateway()))
|
|
self._set_device_info_value(dt, "route", gateway)
|
|
if dt == "wired":
|
|
prefix = ipv4cfg.get_addresses()[0].get_prefix()
|
|
nm_utils.nm_utils_ip4_prefix_to_netmask.argtypes = [ctypes.c_uint32]
|
|
nm_utils.nm_utils_ip4_prefix_to_netmask.restype = ctypes.c_uint32
|
|
netmask = nm_utils.nm_utils_ip4_prefix_to_netmask(prefix)
|
|
netmask = socket.inet_ntoa(struct.pack('=L', netmask))
|
|
self._set_device_info_value(dt, "subnet", netmask)
|
|
else:
|
|
self._set_device_info_value(dt, "ipv4", None)
|
|
self._set_device_info_value(dt, "dns", None)
|
|
self._set_device_info_value(dt, "route", None)
|
|
if dt == "wired":
|
|
self._set_device_info_value(dt, "subnet", None)
|
|
|
|
# TODO NM_GI_BUGS - segfaults on get_addres(), get_prefix()
|
|
ipv6_addr = None
|
|
if (ipv6cfg
|
|
and state == NetworkManager.DeviceState.ACTIVATED):
|
|
config = dbus.SystemBus().get_object(NM_SERVICE, ipv6cfg.get_path())
|
|
addr, prefix, gw = getNMObjProperty(config, ".IP6Config",
|
|
"Addresses")[0]
|
|
ipv6_addr = socket.inet_ntop(socket.AF_INET6, "".join(chr(byte) for byte in addr))
|
|
self._set_device_info_value(dt, "ipv6", ipv6_addr)
|
|
|
|
if ipv4cfg and ipv6_addr:
|
|
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 ipv6_addr:
|
|
self.builder.get_object("heading_%s_ipv6" % dt).set_label(_("IP Address"))
|
|
|
|
return False
|
|
|
|
def _refresh_ap(self, device, state=None):
|
|
if device.get_device_type() != NetworkManager.DeviceType.WIFI:
|
|
return
|
|
|
|
if state is None:
|
|
state = device.get_state()
|
|
if state == NetworkManager.DeviceState.UNAVAILABLE:
|
|
ap_str = None
|
|
else:
|
|
active_ap = device.get_active_access_point()
|
|
if active_ap:
|
|
active_ap_dbus = dbus.SystemBus().get_object(NM_SERVICE,
|
|
active_ap.get_path())
|
|
ap_str = self._ap_security_string_dbus(active_ap_dbus)
|
|
# TODO NM_GI_BUGS move to gi after fixed in NM
|
|
# - NetworkManager.80211ApFlags
|
|
# - active_ap.get_flags, get_wpa_flags, get_rsn_flags
|
|
#ap_str = self._ap_security_string(active_ap)
|
|
else:
|
|
ap_str = ""
|
|
|
|
self._set_device_info_value("wireless", "security", ap_str)
|
|
|
|
if state == NetworkManager.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(device.get_access_points())
|
|
for ap in aps:
|
|
active = active_ap and active_ap.get_path() == ap.get_path()
|
|
self._add_ap(ap, active)
|
|
# 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[1] == active_ap.get_ssid():
|
|
combobox.set_active_iter(i.iter)
|
|
self.selected_ssid = active_ap.get_ssid()
|
|
break
|
|
self._updating_device = False
|
|
|
|
def _refresh_speed_hwaddr(self, device, state=None):
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
dt = "wired"
|
|
speed = device.get_speed()
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
dt = "wireless"
|
|
speed = device.get_bitrate() / 1000
|
|
|
|
if state is None:
|
|
state = device.get_state()
|
|
if state == NetworkManager.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)
|
|
self._set_device_info_value(dt, "mac", device.get_hw_address())
|
|
|
|
def _refresh_device_type_page(self, device):
|
|
notebook = self.builder.get_object("notebook_types")
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
notebook.set_current_page(0)
|
|
elif dev_type == NetworkManager.DeviceType.WIFI:
|
|
notebook.set_current_page(1)
|
|
|
|
def _refresh_carrier_info(self):
|
|
for i in self.builder.get_object("liststore_devices"):
|
|
i[DEVICES_COLUMN_TITLE] = self._dev_title(i[DEVICES_COLUMN_OBJECT])
|
|
|
|
def _refresh_header_ui(self, device, state=None):
|
|
dev_type = device.get_device_type()
|
|
if dev_type == NetworkManager.DeviceType.ETHERNET:
|
|
dev_type_str = "wired"
|
|
elif dev_type == NetworkManager.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(device), Gtk.IconSize.DIALOG)
|
|
|
|
# TODO: is this necessary? Isn't it static from glade?
|
|
self.builder.get_object("label_%s_device" % dev_type_str).set_label(
|
|
"%s (%s)" % (self._dev_type_str(device), device.get_iface()))
|
|
|
|
if state is None:
|
|
state = device.get_state()
|
|
self.builder.get_object("label_%s_status" % dev_type_str).set_label(
|
|
localized_string_of_device_state(device))
|
|
|
|
switch = self.builder.get_object("device_%s_off_switch" % dev_type_str)
|
|
if dev_type_str == "wired":
|
|
switch.set_visible(state not in (NetworkManager.DeviceState.UNAVAILABLE,
|
|
NetworkManager.DeviceState.UNMANAGED))
|
|
self._updating_device = True
|
|
switch.set_active(state not in (NetworkManager.DeviceState.UNMANAGED,
|
|
NetworkManager.DeviceState.UNAVAILABLE,
|
|
NetworkManager.DeviceState.DISCONNECTED,
|
|
NetworkManager.DeviceState.DEACTIVATING,
|
|
NetworkManager.DeviceState.FAILED))
|
|
self._updating_device = False
|
|
if not configuration_of_disconnected_devices_allowed:
|
|
self.builder.get_object("button_%s_options" % dev_type_str).set_sensitive(state == NetworkManager.DeviceState.ACTIVATED)
|
|
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:
|
|
heading.hide()
|
|
value_label.hide()
|
|
else:
|
|
heading.show()
|
|
value_label.show()
|
|
value_label.set_label(value_str)
|
|
|
|
# TODO NM_GI_BUGS use glib methods for mode and security (dbus obj or nm obj?)
|
|
def _add_ap(self, ap, active=False):
|
|
ssid = ap.get_ssid()
|
|
if not ssid:
|
|
return
|
|
|
|
# TODO NM_GI_BUGS
|
|
ap_dbus = dbus.SystemBus().get_object(NM_SERVICE, ap.get_path())
|
|
mode = getNMObjProperty(ap_dbus, ".AccessPoint", "Mode")
|
|
|
|
security = self._ap_security_dbus(ap)
|
|
|
|
store = self.builder.get_object("liststore_wireless_network")
|
|
# the third column is for sorting
|
|
iter = store.append([ap.get_path(),
|
|
ssid,
|
|
ssid,
|
|
ap.get_strength(),
|
|
mode,
|
|
security])
|
|
if active:
|
|
self.builder.get_object("combobox_wireless_network_name").set_active_iter(iter)
|
|
|
|
def _get_strongest_unique_aps(self, access_points):
|
|
strongest_aps = {}
|
|
for ap in access_points:
|
|
ssid = ap.get_ssid()
|
|
if ssid in strongest_aps:
|
|
#print "DBG: found %s duplicate" % ssid
|
|
if ap.get_strength() > strongest_aps[ssid].get_strength():
|
|
strongest_aps[ssid] = ap
|
|
#print "DBG: ...stronger"
|
|
else:
|
|
strongest_aps[ssid] = ap
|
|
#print "DBG: adding %s ap" % ssid
|
|
|
|
return strongest_aps.values()
|
|
|
|
# TODO NM_GI_BUGS fix as _ap_security_string
|
|
def _ap_security_dbus(self, ap):
|
|
if ap.get_path() == "/":
|
|
return NM_AP_SEC_UNKNOWN
|
|
|
|
ap_dbus = dbus.SystemBus().get_object(NM_SERVICE, ap.get_path())
|
|
flags = getNMObjProperty(ap_dbus, ".AccessPoint", "Flags")
|
|
wpa_flags = getNMObjProperty(ap_dbus, ".AccessPoint", "WpaFlags")
|
|
rsn_flags = getNMObjProperty(ap_dbus, ".AccessPoint", "RsnFlags")
|
|
|
|
if (not (flags & NM_802_11_AP_FLAGS_PRIVACY) and
|
|
wpa_flags == NM_802_11_AP_SEC_NONE and
|
|
rsn_flags == NM_802_11_AP_SEC_NONE):
|
|
type = NM_AP_SEC_NONE
|
|
elif (flags & NM_802_11_AP_FLAGS_PRIVACY and
|
|
wpa_flags == NM_802_11_AP_SEC_NONE and
|
|
rsn_flags == NM_802_11_AP_SEC_NONE):
|
|
type = NM_AP_SEC_WEP
|
|
elif (not (flags & NM_802_11_AP_FLAGS_PRIVACY) and
|
|
wpa_flags != NM_802_11_AP_SEC_NONE and
|
|
rsn_flags != NM_802_11_AP_SEC_NONE):
|
|
type = NM_AP_SEC_WPA
|
|
else:
|
|
type = NM_AP_SEC_WPA2
|
|
|
|
return type
|
|
|
|
## TODO NM_GI_BUGS - attribute starts with number
|
|
# def _ap_security_string(self, ap):
|
|
# if ap.object_path == "/":
|
|
# return ""
|
|
#
|
|
# flags = ap.get_flags()
|
|
# wpa_flags = ap.get_wpa_flags()
|
|
# rsn_flags = ap.get_rsn_flags()
|
|
#
|
|
# sec_str = ""
|
|
#
|
|
# if ((flags & NetworkManager.80211ApFlags.PRIVACY) and
|
|
# wpa_flags == NetworkManager.80211ApSecurityFlags.NONE and
|
|
# rsn_flags == NetworkManager.80211ApSecurityFlags.NONE):
|
|
# sec_str += "%s, " % _("WEP")
|
|
#
|
|
# if wpa_flags != NetworkManager.80211ApSecurityFlags.NONE:
|
|
# sec_str += "%s, " % _("WPA")
|
|
#
|
|
# if rsn_flags != NetworkManager.80211ApSecurityFlags.NONE:
|
|
# sec_str += "%s, " % _("WPA2")
|
|
#
|
|
# if ((wpa_flags & NetworkManager.80211ApSecurityFlags.KEY_MGMT_802_1X) or
|
|
# (rsn_flags & NetworkManager.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_security_string_dbus(self, ap):
|
|
if ap.object_path == "/":
|
|
return ""
|
|
|
|
flags = getNMObjProperty(ap, ".AccessPoint", "Flags")
|
|
wpa_flags = getNMObjProperty(ap, ".AccessPoint", "WpaFlags")
|
|
rsn_flags = getNMObjProperty(ap, ".AccessPoint", "RsnFlags")
|
|
|
|
sec_str = ""
|
|
|
|
if ((flags & NM_802_11_AP_FLAGS_PRIVACY) and
|
|
wpa_flags == NM_802_11_AP_SEC_NONE and
|
|
rsn_flags == NM_802_11_AP_SEC_NONE):
|
|
sec_str += "%s, " % _("WEP")
|
|
|
|
if wpa_flags != NM_802_11_AP_SEC_NONE:
|
|
sec_str += "%s, " % _("WPA")
|
|
|
|
if rsn_flags != NM_802_11_AP_SEC_NONE:
|
|
sec_str += "%s, " % _("WPA2")
|
|
|
|
if ((wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) or
|
|
(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)):
|
|
sec_str += "%s, " % _("Enterprise")
|
|
|
|
if sec_str:
|
|
sec_str = sec_str[:-2]
|
|
else:
|
|
sec_str = _("None")
|
|
|
|
return sec_str
|
|
|
|
@property
|
|
def listed_devices(self):
|
|
return [row[DEVICES_COLUMN_OBJECT] for
|
|
row in self.builder.get_object("liststore_devices")]
|
|
|
|
@property
|
|
def hostname(self):
|
|
return self.entry_hostname.get_text()
|
|
|
|
@hostname.setter
|
|
def hostname(self, value):
|
|
self.entry_hostname.set_text(value)
|
|
|
|
class NetworkSpoke(NormalSpoke):
|
|
builderObjects = ["networkWindow", "liststore_wireless_network", "liststore_devices"]
|
|
mainWidgetName = "networkWindow"
|
|
uiFile = "spokes/network.glade"
|
|
|
|
title = N_("NETWORK CONFIGURATION")
|
|
icon = "network-transmit-receive-symbolic"
|
|
|
|
category = SoftwareCategory
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
NormalSpoke.__init__(self, *args, **kwargs)
|
|
self.network_control_box = NetworkControlBox(self.builder)
|
|
self.network_control_box.hostname = self.data.network.hostname
|
|
self.network_control_box.client.connect("notify::%s" %
|
|
NMClient.CLIENT_STATE,
|
|
self.on_nm_state_changed)
|
|
for device in self.network_control_box.client.get_devices():
|
|
device.connect("state-changed", self.on_device_state_changed)
|
|
|
|
def apply(self):
|
|
# TODO: sanity check
|
|
self.data.network.network = []
|
|
for dev in self.network_control_box.listed_devices:
|
|
network_data = getKSNetworkData(dev)
|
|
if network_data is not None:
|
|
self.data.network.network.append(network_data)
|
|
hostname = self.network_control_box.hostname
|
|
update_hostname(self.data, hostname)
|
|
|
|
@property
|
|
def completed(self):
|
|
# TODO: check also if source requires updates when implemented
|
|
return (self.data.method.method not in ("url", "nfs") or
|
|
len(self.network_control_box.activated_connections()) > 0)
|
|
|
|
@property
|
|
def status(self):
|
|
""" A short string describing which devices are connected. """
|
|
msg = _("Unknown")
|
|
|
|
state = self.network_control_box.client.get_state()
|
|
if state == NetworkManager.State.CONNECTING:
|
|
msg = _("Connecting...")
|
|
elif state == NetworkManager.State.DISCONNECTING:
|
|
msg = _("Disconnecting...")
|
|
else:
|
|
ac = self.network_control_box.activated_connections()
|
|
if ac:
|
|
if len(ac) == 1:
|
|
device, ssid = ac[0]
|
|
if ssid:
|
|
msg = _("Wireless connected to %s" %
|
|
ssid)
|
|
else:
|
|
msg = _("Wired (%s) connected") % device
|
|
else:
|
|
|
|
devlist = ", ".join(["%s" % device for device, ssid
|
|
in ac
|
|
if ssid is None] +
|
|
["%s" % ssid for device, ssid
|
|
in ac
|
|
if ssid is not None])
|
|
|
|
msg = _("Connected: %s") % devlist
|
|
else:
|
|
msg = _("Not connected")
|
|
|
|
if not self.network_control_box.listed_devices:
|
|
msg = _("No network devices available")
|
|
|
|
return msg
|
|
|
|
@property
|
|
def showable(self):
|
|
return not (flags.livecdInstall or flags.imageInstall)
|
|
|
|
def initialize(self):
|
|
NormalSpoke.initialize(self)
|
|
self.network_control_box.initialize()
|
|
|
|
def refresh(self):
|
|
NormalSpoke.refresh(self)
|
|
self.network_control_box.refresh()
|
|
|
|
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, *args):
|
|
new_state = args[1]
|
|
if new_state in (NetworkManager.DeviceState.ACTIVATED,
|
|
NetworkManager.DeviceState.DISCONNECTED,
|
|
NetworkManager.DeviceState.UNAVAILABLE):
|
|
gtk_call_once(self._update_status)
|
|
|
|
def _update_status(self):
|
|
communication.send_message(self.__class__.__name__, self.status)
|
|
|
|
def _update_hostname(self):
|
|
if self.network_control_box.hostname == "localhost.localdomain":
|
|
update_hostname(self.data)
|
|
self.network_control_box.hostname = self.data.network.hostname
|
|
|
|
def on_back_clicked(self, button):
|
|
hostname = self.network_control_box.hostname
|
|
(valid, error) = sanityCheckHostname(hostname)
|
|
if not valid:
|
|
self.clear_info()
|
|
msg = _("Hostname is not valid: %s") % error
|
|
self.set_warning(msg)
|
|
self.network_control_box.entry_hostname.grab_focus()
|
|
self.window.show_all()
|
|
else:
|
|
self.clear_info()
|
|
NormalSpoke.on_back_clicked(self, button)
|
|
|
|
class NetworkStandaloneSpoke(StandaloneSpoke):
|
|
builderObjects = ["networkStandaloneWindow", "networkControlBox_vbox", "liststore_wireless_network", "liststore_devices"]
|
|
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)
|
|
self.network_control_box.hostname = self.data.network.hostname
|
|
parent = self.builder.get_object("AnacondaStandaloneWindow-action_area5")
|
|
parent.add(self.network_control_box.vbox)
|
|
|
|
self.network_control_box.client.connect("notify::%s" %
|
|
NMClient.CLIENT_STATE,
|
|
self.on_nm_state_changed)
|
|
|
|
self._initially_available = self.completed
|
|
log.debug("network standalone spoke (init): completed: %s" % self._initially_available)
|
|
self._now_available = False
|
|
|
|
def apply(self):
|
|
self.data.network.network = []
|
|
for dev in self.network_control_box.listed_devices:
|
|
network_data = getKSNetworkData(dev)
|
|
if network_data is not None:
|
|
self.data.network.network.append(network_data)
|
|
hostname = self.network_control_box.hostname
|
|
update_hostname(self.data, hostname)
|
|
|
|
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:
|
|
from pyanaconda.packaging import payloadInitialize
|
|
from pyanaconda.threads import threadMgr, AnacondaThread
|
|
|
|
payloadThread = threadMgr.get("AnaPayloadThread")
|
|
if payloadThread:
|
|
payloadThread.join()
|
|
|
|
threadMgr.add(AnacondaThread(name="AnaPayloadThread", target=payloadInitialize, args=(self.storage, self.data, self.payload)))
|
|
|
|
@property
|
|
def completed(self):
|
|
return len(self.network_control_box.activated_connections()) > 0
|
|
|
|
def initialize(self):
|
|
StandaloneSpoke.initialize(self)
|
|
self.network_control_box.initialize()
|
|
|
|
def refresh(self):
|
|
StandaloneSpoke.refresh(self)
|
|
self.network_control_box.refresh()
|
|
|
|
def _on_continue_clicked(self, cb):
|
|
hostname = self.network_control_box.hostname
|
|
(valid, error) = sanityCheckHostname(hostname)
|
|
if not valid:
|
|
self.clear_info()
|
|
msg = _("Hostname is not valid: %s") % error
|
|
self.set_warning(msg)
|
|
self.network_control_box.entry_hostname.grab_focus()
|
|
self.window.show_all()
|
|
else:
|
|
self.clear_info()
|
|
StandaloneSpoke._on_continue_clicked(self, cb)
|
|
|
|
# Use case: slow dhcp has connected when on spoke
|
|
def on_nm_state_changed(self, *args):
|
|
gtk_call_once(self._update_hostname)
|
|
|
|
def _update_hostname(self):
|
|
if self.network_control_box.hostname == "localhost.localdomain":
|
|
update_hostname(self.data)
|
|
self.network_control_box.hostname = self.data.network.hostname
|
|
|
|
def getKSNetworkData(device):
|
|
retval = None
|
|
|
|
ifcfg_suffix = None
|
|
if device.get_device_type() == NetworkManager.DeviceType.ETHERNET:
|
|
ifcfg_suffix = device.get_iface()
|
|
elif device.get_device_type() == NetworkManager.DeviceType.WIFI:
|
|
ap = device.get_active_access_point()
|
|
if ap:
|
|
ifcfg_suffix = ap.get_ssid()
|
|
|
|
if ifcfg_suffix:
|
|
ifcfg_suffix = ifcfg_suffix.replace(' ', '_')
|
|
device_cfg = NetworkDevice(netscriptsDir, ifcfg_suffix)
|
|
device_cfg.loadIfcfgFile()
|
|
retval = kickstartNetworkData(ifcfg=device_cfg)
|
|
if device.get_iface() in getActiveNetDevs():
|
|
retval.activate = True
|
|
|
|
return retval
|
|
|
|
if __name__ == "__main__":
|
|
|
|
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)
|
|
n.initialize()
|
|
n.refresh()
|
|
|
|
n.vbox.reparent(win)
|
|
|
|
win.show_all()
|
|
Gtk.main()
|