[PATCH][master][RHEL] move Xorg test up so we might start vnc instead
by Mark Hamzy
Move the want_x set and check up so that, if disabled, we might still start
the VNC pathway instead. We do not need X for that path.
Also, add so more warning messages so we might know why exactly we are not
going to ask for the VNC path.
---
anaconda | 47 ++++++++++++++++++++++++++---------------------
1 file changed, 26 insertions(+), 21 deletions(-)
diff --git a/anaconda b/anaconda
index 604ad1d..a4fdefa 100755
--- a/anaconda
+++ b/anaconda
@@ -469,47 +469,32 @@ def setupDisplay(anaconda, opts, addon_paths=None):
# disable VNC over text question when not enough memory is available
if blivet.util.total_memory() < isys.MIN_GUI_RAM:
+ stdoutLog.warning("Not asking for VNC because current memory (%d) < MIN_GUI_RAM (%d)" % (iutil.memInstalled(), isys.MIN_GUI_RAM))
flags.vncquestion = False
# disable VNC question if text mode is requested and this is a ks install
if anaconda.displayMode == 't' and flags.automatedInstall:
+ stdoutLog.warning("Not asking for VNC because of an automated install")
flags.vncquestion = False
# disable VNC question if we were explicitly asked for text in kickstart
if anaconda.ksdata.displaymode.displayMode == DISPLAY_MODE_TEXT:
+ stdoutLog.warning("Not asking for VNC because text mode was explicitly asked for in kickstart")
flags.vncquestion = False
# disable VNC question if we don't have network
if not nm_is_connected():
+ stdoutLog.warning("Not asking for VNC because we don't have a network")
flags.vncquestion = False
- # disable VNC question if we don't have X
+ # disable VNC question if we don't have Xvnc
if not os.access('/usr/bin/Xvnc', os.X_OK):
+ stdoutLog.warning("Not asking for VNC because we don't have Xvnc")
flags.vncquestion = False
if os.environ.has_key('DISPLAY'):
flags.preexisting_x11 = True
- if anaconda.displayMode == 't' and flags.vncquestion:
- #we prefer vnc over text mode, so ask about that
- message = _("Text mode provides a limited set of installation "
- "options. It does not allow you to specify your "
- "own partitioning layout or package selections. "
- "Would you like to use VNC mode instead?")
-
- app = App("VNC Question")
- spoke = AskVNCSpoke(app, anaconda.ksdata, message=message)
- app.schedule_screen(spoke)
- app.run()
-
- if anaconda.ksdata.vnc.enabled:
- anaconda.displayMode = 'g'
- flags.usevnc = 1
- vncS.password = anaconda.ksdata.vnc.password
-
- log.info("Display mode = %s" % anaconda.displayMode)
- check_memory(anaconda, opts)
-
# Should we try to start Xorg?
want_x = anaconda.displayMode == 'g' and \
not (flags.preexisting_x11 or flags.usevnc)
@@ -530,6 +515,26 @@ def setupDisplay(anaconda, opts, addon_paths=None):
anaconda.displayMode = 't'
want_x = False
+ if anaconda.displayMode == 't' and flags.vncquestion:
+ #we prefer vnc over text mode, so ask about that
+ message = _("Text mode provides a limited set of installation "
+ "options. It does not allow you to specify your "
+ "own partitioning layout or package selections. "
+ "Would you like to use VNC mode instead?")
+
+ app = App("VNC Question")
+ spoke = AskVNCSpoke(app, anaconda.ksdata, message=message)
+ app.schedule_screen(spoke)
+ app.run()
+
+ if anaconda.ksdata.vnc.enabled:
+ anaconda.displayMode = 'g'
+ flags.usevnc = 1
+ vncS.password = anaconda.ksdata.vnc.password
+
+ log.info("Display mode = %s" % anaconda.displayMode)
+ check_memory(anaconda, opts)
+
if want_x:
# The following code depends on no SIGCHLD being delivered,
# possibly only except the one from a failing X.org. Thus
--
1.8.1.2
11 years, 1 month
[master] Tuesday's "friday refactorization"
by Vratislav Podzimek
This patch ruins a git history a bit so I'm not sure we want to do this
or just stick to this in changes and new code comming in future.
Vratislav Podzimek (1):
Don't create temporary lists if not needed
pyanaconda/anaconda_optparse.py | 2 +-
pyanaconda/bootloader.py | 2 +-
pyanaconda/network.py | 2 +-
pyanaconda/packaging/__init__.py | 2 +-
pyanaconda/packaging/yumpayload.py | 2 +-
pyanaconda/ui/gui/spokes/custom.py | 8 ++++----
pyanaconda/ui/gui/spokes/network.py | 4 ++--
pyanaconda/ui/gui/spokes/user.py | 4 ++--
pyanaconda/ui/tui/simpleline/base.py | 2 +-
9 files changed, 14 insertions(+), 14 deletions(-)
--
1.7.11.7
11 years, 1 month
[PATCH] Fix reclaiming disk space for non-us installations.
by Radek Vykydal
---
pyanaconda/ui/gui/spokes/lib/resize.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/lib/resize.py b/pyanaconda/ui/gui/spokes/lib/resize.py
index 7baf894..4353ad8 100644
--- a/pyanaconda/ui/gui/spokes/lib/resize.py
+++ b/pyanaconda/ui/gui/spokes/lib/resize.py
@@ -320,9 +320,9 @@ class ResizeDialog(GUIObject):
# If the user marked a whole disk for deletion, they can't go in and
# un-delete partitions under it.
- if newAction == _(DELETE):
+ if newAction == DELETE:
self._diskStore[partItr][EDITABLE_COL] = False
- elif newAction == _(PRESERVE):
+ elif newAction == PRESERVE:
part = self.storage.devicetree.getDeviceByID(self._diskStore[partItr][DEVICE_ID_COL])
self._diskStore[partItr][EDITABLE_COL] = not part.protected
--
1.7.11.7
11 years, 1 month
[lorax] Add explicit install of net-tools
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
---
share/runtime-install.tmpl | 1 +
1 file changed, 1 insertion(+)
diff --git a/share/runtime-install.tmpl b/share/runtime-install.tmpl
index 686fb0d..8c62915 100644
--- a/share/runtime-install.tmpl
+++ b/share/runtime-install.tmpl
@@ -89,6 +89,7 @@ installpkg tigervnc-server-minimal
installpkg tigervnc-server-module
%endif
installpkg chrony rdate
+installpkg net-tools
## hardware utilities/libraries
installpkg pciutils usbutils
--
1.8.1.2
11 years, 1 month
[pykickstart] Make sure tests can run and report import errors
by Brian C. Lane
From: "Brian C. Lane" <bcl(a)redhat.com>
---
tests/baseclass.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tests/baseclass.py b/tests/baseclass.py
index 9d9e8c3..b4f183b 100644
--- a/tests/baseclass.py
+++ b/tests/baseclass.py
@@ -169,7 +169,7 @@ def loadModules(moduleDir, cls_pattern="_TestCase", skip_list=["__init__", "base
found = imputil.imp.find_module(module)
loaded = imputil.imp.load_module(module, found[0], found[1], found[2])
except ImportError, e:
- print(_("Error loading module %s.") % module)
+ print(_("Error loading module %s: %s") % (module, e))
continue
# Find class names that match the supplied pattern (default: "_TestCase")
@@ -188,6 +188,8 @@ def loadModules(moduleDir, cls_pattern="_TestCase", skip_list=["__init__", "base
# Run the tests
if __name__ == "__main__":
+ # Make sure PWD is in the path before the eggs, system paths, etc.
+ sys.path.insert(0, os.environ.get("PWD"))
# Create a test suite
PyKickstartTestSuite = unittest.TestSuite()
--
1.8.1.2
11 years, 1 month
[PATCH] Disable grub2-mkconfig's submenus by default.
by Peter Jones
They are hideous and confusing and serve no useful purpose. Make them
go away.
Signed-off-by: Peter Jones <pjones(a)redhat.com>
---
pyanaconda/bootloader.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py
index a8ad105..bf2a921 100644
--- a/pyanaconda/bootloader.py
+++ b/pyanaconda/bootloader.py
@@ -1439,6 +1439,7 @@ class GRUB2(GRUB):
defaults.write("GRUB_TIMEOUT=%d\n" % self.timeout)
defaults.write("GRUB_DISTRIBUTOR=\"$(sed 's, release .*$,,g' /etc/system-release)\"\n")
defaults.write("GRUB_DEFAULT=saved\n")
+ defaults.write("GRUB_DISABLE_SUBMENU=true\n")
if self.console and self.console.startswith("ttyS"):
defaults.write("GRUB_TERMINAL=\"serial console\"\n")
defaults.write("GRUB_SERIAL_COMMAND=\"%s\"\n" % self.serial_command)
--
1.8.1.4
11 years, 1 month
[PATCH] Catch error when incorrect nfs address entered
by Samantha N. Bueno
Prevents traceback; warn user instead if incorrect address entered
---
pyanaconda/ui/gui/spokes/source.py | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/spokes/source.py b/pyanaconda/ui/gui/spokes/source.py
index 6381130..5c0aaab 100644
--- a/pyanaconda/ui/gui/spokes/source.py
+++ b/pyanaconda/ui/gui/spokes/source.py
@@ -526,7 +526,14 @@ class SourceSpoke(NormalSpoke):
return
self.data.method.method = "nfs"
- (self.data.method.server, self.data.method.dir) = url.split(":", 2)
+ try:
+ (self.data.method.server, self.data.method.dir) = url.split(":", 2)
+ except ValueError as e:
+ log.error("ValueError: %s" % (e,))
+ gtk_call_once(self.set_warning, _("Failed to set up installation source; check the repo url"))
+ self._error = True
+ return
+
self.data.method.opts = self.builder.get_object("nfsOptsEntry").get_text() or ""
if (old_source.method == "nfs" and
--
1.7.11.7
11 years, 1 month
[PATCH 1/6] Add a summary screen of actions to be performed on all disks.
by Chris Lumens
---
po/POTFILES.in | 2 +
pyanaconda/ui/gui/spokes/lib/summary.glade | 204 +++++++++++++++++++++++++++++
pyanaconda/ui/gui/spokes/lib/summary.py | 66 ++++++++++
3 files changed, 272 insertions(+)
create mode 100644 pyanaconda/ui/gui/spokes/lib/summary.glade
create mode 100644 pyanaconda/ui/gui/spokes/lib/summary.py
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c2ad78d..f9f3e79 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -72,6 +72,7 @@ pyanaconda/ui/gui/spokes/lib/accordion.py
pyanaconda/ui/gui/spokes/lib/cart.py
pyanaconda/ui/gui/spokes/lib/passphrase.py
pyanaconda/ui/gui/spokes/lib/resize.py
+pyanaconda/ui/gui/spokes/lib/summary.py
# Interface files.
pyanaconda/ui/gui/spokes/advanced_user.glade
@@ -89,6 +90,7 @@ pyanaconda/ui/gui/spokes/lib/cart.glade
pyanaconda/ui/gui/spokes/lib/detailederror.glade
pyanaconda/ui/gui/spokes/lib/passphrase.glade
pyanaconda/ui/gui/spokes/lib/resize.glade
+pyanaconda/ui/gui/spokes/lib/summary.glade
pyanaconda/ui/gui/main.glade
pyanaconda/ui/gui/hubs/summary.glade
pyanaconda/ui/gui/hubs/progress.glade
diff --git a/pyanaconda/ui/gui/spokes/lib/summary.glade b/pyanaconda/ui/gui/spokes/lib/summary.glade
new file mode 100644
index 0000000..3d020e8
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/lib/summary.glade
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkListStore" id="actionStore">
+ <columns>
+ <!-- column-name actionOrder -->
+ <column type="gint"/>
+ <!-- column-name actionType -->
+ <column type="gchararray"/>
+ <!-- column-name actionFormatType -->
+ <column type="gchararray"/>
+ <!-- column-name actionDeviceName -->
+ <column type="gchararray"/>
+ <!-- column-name actionMountpoint -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="summaryDialog">
+ <property name="height_request">400</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">SUMMARY OF CHANGES</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <property name="decorated">False</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="summaryCancelButton">
+ <property name="label" translatable="yes">_Cancel & Return to Custom Partitioning</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ <property name="non_homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="summaryAcceptButton">
+ <property name="label" translatable="yes">_Accept Changes</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ <property name="non_homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">SUMMARY OF CHANGES</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Your customizations will result in the following changes taking effect on the disks you've selected:</property>
+ <property name="wrap">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTreeView" id="actionView">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="model">actionStore</property>
+ <property name="headers_clickable">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="orderColumn">
+ <property name="title" translatable="yes">Order</property>
+ <child>
+ <object class="GtkCellRendererText" id="orderRenderer"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="actionColumn">
+ <property name="title" translatable="yes">Action</property>
+ <child>
+ <object class="GtkCellRendererText" id="actionRenderer"/>
+ <attributes>
+ <attribute name="markup">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="typeColumn">
+ <property name="title" translatable="yes">Type</property>
+ <child>
+ <object class="GtkCellRendererText" id="typeRenderer"/>
+ <attributes>
+ <attribute name="text">2</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="deviceNameColumn">
+ <property name="title" translatable="yes">Device Name</property>
+ <child>
+ <object class="GtkCellRendererText" id="deviceNameRenderer"/>
+ <attributes>
+ <attribute name="text">3</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="mountpointColumn">
+ <property name="title" translatable="yes">Mountpoint</property>
+ <child>
+ <object class="GtkCellRendererText" id="mountpointRenderer"/>
+ <attributes>
+ <attribute name="text">4</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="0">summaryCancelButton</action-widget>
+ <action-widget response="1">summaryAcceptButton</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/pyanaconda/ui/gui/spokes/lib/summary.py b/pyanaconda/ui/gui/spokes/lib/summary.py
new file mode 100644
index 0000000..a4a0899
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/lib/summary.py
@@ -0,0 +1,66 @@
+# Action summary dialog
+#
+# Copyright (C) 2013 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): Chris Lumens <clumens(a)redhat.com>
+#
+
+from gi.repository import Gtk
+
+from pyanaconda.ui.gui import GUIObject
+
+from blivet.deviceaction import ACTION_TYPE_DESTROY, ACTION_TYPE_RESIZE, ACTION_OBJECT_FORMAT
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+
+__all__ = ["ActionSummaryDialog"]
+
+class ActionSummaryDialog(GUIObject):
+ builderObjects = ["actionStore", "summaryDialog"]
+ mainWidgetName = "summaryDialog"
+ uiFile = "spokes/lib/summary.glade"
+
+ def initialize(self, actions):
+ for (i, action) in enumerate(actions, start=1):
+ mountpoint = ""
+
+ if action.type in [ACTION_TYPE_DESTROY, ACTION_TYPE_RESIZE]:
+ typeString = """<span foreground='red'>%s</span>""" % action.typeDesc.title()
+ else:
+ typeString = """<span foreground='green'>%s</span>""" % action.typeDesc.title()
+ if action.obj == ACTION_OBJECT_FORMAT:
+ mountpoint = getattr(action.device.format, "mountpoint", "")
+
+ self._store.append([i,
+ typeString,
+ action.objectTypeString,
+ action.device.name,
+ mountpoint])
+
+ def refresh(self, actions):
+ GUIObject.refresh(self)
+
+ self._store = self.builder.get_object("actionStore")
+
+ self._store.clear()
+ self.initialize(actions)
+
+ def run(self):
+ rc = self.window.run()
+ self.window.destroy()
+ return rc
--
1.8.1.2
11 years, 1 month
[PATCH] Don't set ibft device renaming for dracut, let it just do its job (#828505)
by Radek Vykydal
We need also modify dracut to write out BOOTPROTO=ibft for ip=ibft
---
pyanaconda/network.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py
index 9ed2bc7..1f05a6c 100644
--- a/pyanaconda/network.py
+++ b/pyanaconda/network.py
@@ -390,9 +390,9 @@ def dracutBootArguments(ifcfg, storage_ipaddr, hostname=None):
netargs.add("ip=%s::%s:%s:%s:%s:none" % (ifcfg.get('ipaddr'),
gateway, netmask, hostname, devname))
- hwaddr = ifcfg.get("HWADDR")
- if hwaddr:
- netargs.add("ifname=%s:%s" % (devname, hwaddr.lower()))
+ hwaddr = ifcfg.get("HWADDR")
+ if hwaddr:
+ netargs.add("ifname=%s:%s" % (devname, hwaddr.lower()))
nettype = ifcfg.get("NETTYPE")
subchannels = ifcfg.get("SUBCHANNELS")
--
1.7.11.7
11 years, 1 month
[PATCH] Network spoke: improve message format parametrization for translators
by Radek Vykydal
---
pyanaconda/ui/gui/spokes/network.py | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py
index 2fff63c..9d17919 100644
--- a/pyanaconda/ui/gui/spokes/network.py
+++ b/pyanaconda/ui/gui/spokes/network.py
@@ -1147,13 +1147,17 @@ class NetworkSpoke(NormalSpoke):
if len(ac) == 1:
name, type, info = ac[0]
if type == NetworkManager.DeviceType.ETHERNET:
- msg = _("Wired (%s) connected") % name
+ msg = _("Wired (%(interface_name)s) connected") \
+ % {"interface_name": name}
elif type == NetworkManager.DeviceType.WIFI:
- msg = _("Wireless connected to %s") % info
+ msg = _("Wireless connected to %(access_point)s") \
+ % {"access_point" : info}
elif type == NetworkManager.DeviceType.BOND:
- msg = _("Bond %s (%s) connected") % (name, ",".join(info))
+ msg = _("Bond %(interface_name)s (%(list_of_slaves)s) connected") \
+ % {"interface_name": name, "list_of_slaves": ",".join(info)}
if type == NetworkManager.DeviceType.VLAN:
- msg = _("Vlan %s (%s, ID %s) connected") % (name, info[0], info[1])
+ msg = _("Vlan %(interface_name)s (%(parent_device)s, ID %(vlanid)s) connected") \
+ % {"interface_name": name, "parent_device": info[0], "vlanid": info[1]}
else:
devlist = []
for name, type, info in ac:
@@ -1165,7 +1169,8 @@ class NetworkSpoke(NormalSpoke):
devlist.append("%s (%s)" % (name, ",".join(info)))
if type == NetworkManager.DeviceType.VLAN:
devlist.append("%s" % name)
- msg = _("Connected: %s") % ", ".join(devlist)
+ msg = _("Connected: %(list_of_interface_names)s") \
+ % {"list_of_interface_names": ", ".join(devlist)}
else:
msg = _("Not connected")
--
1.7.11.7
11 years, 1 month