Skip to content

Commit

Permalink
network: use consolidated s390 device configuration (#1802482,#1937049)
Browse files Browse the repository at this point in the history
Implements the znet part of referenced bugs.

Depends on https://github.com/ibm-s390-linux/s390-tools commit
("zdev: add helper for ZNET config conversion from zdev to rd.znet").

Dracut commit ("feat(znet): use zdev for consolidated device
configuration"), replaces the distribution-specific persistent
configuration of s390 (channel-attached) network devices with a common
consolidated mechanism using chzdev from s390-tools. So there is no more
ccw.conf nor s390-specific low-level network config in NetworkManager
connections nor ifcfg files.

Therefore, drop NETTYPE and OPTIONS.

Keep SUBCHANNELS nonetheless because it can still serve as a matching key
for NM connections.

Delegate the generation of rd.znet statements to a helper tool from
s390-tools, which gets its low-level config information from the
consolidated mechanism using chzdev.

There are two different code paths involved:

* Root-fs on something (such as iSCSI or NFS) that depends on znet
  =>_get_dracut_znet_argument_from_connection().
  Related earlier commits:
  commit fa174ab ("Write rd_CCW when root fs is on a network device on s390x (#577193)")
  and lately replacing former code:
  commit f85682f ("network module: add support for getting dracut arguments")
  commit 7cf4d64 ("network module: use network module to get dracut arguments")
  and finally replacing initscripts ifcfg by NetworkManager connection:
  commit 840c984 ("network: generate dracut arguments from connections (#1751189)")
  (Note that this generated rd.znet is independent of the (last) one just
  inherited from the boot parameters between commit 64fb106 ("Preserve
  network args on s390x.") and commit a4ba9ae ("Do not pass rd.znet on
  to installed system unconditionally").)

* Configure znet on boot with rd.znet= but without any corresponding ip=
  and instead use the kickstart command "network" to perform high-level
  configuration of the network interface created with rd.znet. This creates
  a non-initramfs NM connection.
  => pyanaconda.modules.network.initialization.ApplyKickstartTask.run
  => pyanaconda.modules.network.nm_client.add_connection_from_ksdata
  => pyanaconda.modules.network.nm_client.create_connections_from_ksdata
  => get_s390_settings() and _update_wired_connection_with_s390_settings()
  (In contrast, early initrd network setups get both the low-level s390
  config and high-level interface config via nm-initrd-generator,
  which parses rd.znet= as well as ip=.)

Signed-off-by: Steffen Maier <maier@linux.ibm.com>
  • Loading branch information
steffen-maier committed Nov 15, 2023
1 parent fe68b5c commit 14c8d97
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 50 deletions.
20 changes: 5 additions & 15 deletions pyanaconda/modules/network/nm_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from pyanaconda.modules.network.utils import get_s390_settings, netmask2prefix, prefix2netmask
from pyanaconda.modules.network.config_file import is_config_file_for_system
from pyanaconda.core.dbus import SystemBus
from pyanaconda.core import util

from pyanaconda.anaconda_loggers import get_module_logger
log = get_module_logger(__name__)
Expand Down Expand Up @@ -437,12 +438,6 @@ def _update_wired_connection_with_s390_settings(connection, s390cfg):
if s390cfg['SUBCHANNELS']:
subchannels = s390cfg['SUBCHANNELS'].split(",")
s_wired.props.s390_subchannels = subchannels
if s390cfg['NETTYPE']:
s_wired.props.s390_nettype = s390cfg['NETTYPE']
if s390cfg['OPTIONS']:
opts = s390cfg['OPTIONS'].split(" ")
opts_dict = {k: v for k, v in (o.split("=") for o in opts)}
s_wired.props.s390_options = opts_dict


def _create_new_connection(network_data, device_name):
Expand Down Expand Up @@ -1376,15 +1371,10 @@ def _get_dracut_znet_argument_from_connection(connection):
argument = ""
wired_setting = connection.get_setting_wired()
if wired_setting and is_s390():
nettype = wired_setting.get_s390_nettype()
# get_s390_subchannels() returns a list of subchannels
subchannels = wired_setting.get_s390_subchannels()
if nettype and subchannels:
argument = "rd.znet={},{}".format(nettype, ",".join(subchannels))
options = wired_setting.get_property(NM.SETTING_WIRED_S390_OPTIONS)
if options:
options_string = ','.join("{}={}".format(key, val) for key, val in options.items())
argument += ",{}".format(options_string)
devspec = util.execWithCapture("/lib/s390-tools/zdev-to-rd.znet",
["persistent",
connection.get_interface_name()]).strip()
argument = "rd.znet={}".format(devspec)
return argument


Expand Down
19 changes: 0 additions & 19 deletions pyanaconda/modules/network/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@
def get_s390_settings(devname):
cfg = {
'SUBCHANNELS': '',
'NETTYPE': '',
'OPTIONS': ''
}

subchannels = []
Expand All @@ -45,23 +43,6 @@ def get_s390_settings(devname):
return cfg
cfg['SUBCHANNELS'] = ','.join(subchannels)

# Example of the ccw.conf file content:
# qeth,0.0.0900,0.0.0901,0.0.0902,layer2=0,portname=FOOBAR,portno=0
#
# SUBCHANNELS="0.0.0900,0.0.0901,0.0.0902"
# NETTYPE="qeth"
# OPTIONS="layer2=1 portname=FOOBAR portno=0"
if not os.path.exists('/run/install/ccw.conf'):
return cfg
with open('/run/install/ccw.conf') as f:
# pylint: disable=redefined-outer-name
for line in f:
if cfg['SUBCHANNELS'] in line:
items = line.strip().split(',')
cfg['NETTYPE'] = items[0]
cfg['OPTIONS'] = " ".join(i for i in items[1:] if '=' in i)
break

return cfg


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,20 @@ def test_get_ports_from_connections(self, get_iface_from_connection):
assert get_ports_from_connections(nm_client, "team", [TEAM1_UUID]) == \
set([("ens11", "ens11", ENS11_UUID)])

@patch("pyanaconda.modules.network.nm_client._get_dracut_znet_argument_from_connection")
@patch("pyanaconda.modules.network.nm_client.get_connections_available_for_iface")
@patch("pyanaconda.modules.network.nm_client.get_ports_from_connections")
@patch("pyanaconda.modules.network.nm_client.is_s390")
def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_connections_mock,
get_connections_available_for_iface):
get_connections_available_for_iface,
_get_dracut_znet_argument_from_connection):
nm_client = Mock()

CON_UUID = "44755f4c-ee12-45b4-ba5e-e10f83de51af"

# IPv4 config auto, IPv6 config auto, mac address specified
is_s390.return_value = False
_get_dracut_znet_argument_from_connection.return_value = ""
ip4_config_attrs = {
"get_method.return_value": NM.SETTING_IP4_CONFIG_METHOD_AUTO,
}
Expand Down Expand Up @@ -162,6 +165,8 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn

# IPv4 config static, mac address not specified, s390
is_s390.return_value = True
_get_dracut_znet_argument_from_connection.return_value = \
"rd.znet=qeth,0.0.0900,0.0.0901,0.0.0902,layer2=1,portname=FOOBAR,portno=0"
address_attrs = {
"get_address.return_value": "10.34.39.44",
"get_prefix.return_value": 24,
Expand All @@ -176,11 +181,6 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn
ip4_config = self._get_mock_objects_from_attrs([ip4_config_attrs])[0]
wired_setting_attrs = {
"get_mac_address.return_value": None,
"get_s390_nettype.return_value": "qeth",
"get_s390_subchannels.return_value": ["0.0.0900", "0.0.0901", "0.0.0902"],
"get_property.return_value": {"layer2": "1",
"portname": "FOOBAR",
"portno": "0"},
}
wired_setting = self._get_mock_objects_from_attrs([wired_setting_attrs])[0]
cons_attrs = [
Expand All @@ -199,6 +199,7 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn

# IPv6 config dhcp
is_s390.return_value = False
_get_dracut_znet_argument_from_connection.return_value = ""
ip6_config_attrs = {
"get_method.return_value": NM.SETTING_IP6_CONFIG_METHOD_DHCP,
}
Expand All @@ -222,6 +223,7 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn

# IPv6 config manual
is_s390.return_value = False
_get_dracut_znet_argument_from_connection.return_value = ""
address_attrs = {
"get_address.return_value": "2001::5",
"get_prefix.return_value": 64,
Expand Down Expand Up @@ -253,6 +255,7 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn

# IPv4 config auto, team
is_s390.return_value = False
_get_dracut_znet_argument_from_connection.return_value = ""
ip4_config_attrs = {
"get_method.return_value": NM.SETTING_IP4_CONFIG_METHOD_AUTO,
}
Expand All @@ -279,6 +282,8 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn

# IPv4 config auto, vlan, s390, parent specified by interface name
is_s390.return_value = True
_get_dracut_znet_argument_from_connection.return_value = \
"rd.znet=qeth,0.0.0900,0.0.0901,0.0.0902,layer2=1,portname=FOOBAR,portno=0"
ip4_config_attrs = {
"get_method.return_value": NM.SETTING_IP4_CONFIG_METHOD_AUTO,
}
Expand All @@ -300,11 +305,6 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn
# Mock parent connection
wired_setting_attrs = {
"get_mac_address.return_value": None,
"get_s390_nettype.return_value": "qeth",
"get_s390_subchannels.return_value": ["0.0.0900", "0.0.0901", "0.0.0902"],
"get_property.return_value": {"layer2": "1",
"portname": "FOOBAR",
"portno": "0"},
}
wired_setting = self._get_mock_objects_from_attrs([wired_setting_attrs])[0]
parent_cons_attrs = [
Expand All @@ -326,6 +326,7 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn
# IPv4 config auto, vlan, parent specified by connection uuid
VLAN_PARENT_UUID = "5e6ead30-d133-4c8c-ba59-818c5ced6a7c"
is_s390.return_value = False
_get_dracut_znet_argument_from_connection.return_value = ""
ip4_config_attrs = {
"get_method.return_value": NM.SETTING_IP4_CONFIG_METHOD_AUTO,
}
Expand Down Expand Up @@ -361,6 +362,8 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn
# IPv4 config auto, vlan, parent specified by connection uuid, s390 (we
# need the parent connection in s390 case, not only parent iface)
is_s390.return_value = True
_get_dracut_znet_argument_from_connection.return_value = \
"rd.znet=qeth,0.0.0900,0.0.0901,0.0.0902,layer2=1,portname=FOOBAR,portno=0"
ip4_config_attrs = {
"get_method.return_value": NM.SETTING_IP4_CONFIG_METHOD_AUTO,
}
Expand All @@ -382,11 +385,6 @@ def test_get_dracut_arguments_from_connection(self, is_s390, get_ports_from_conn
# Mock parent connection
wired_setting_attrs = {
"get_mac_address.return_value": None,
"get_s390_nettype.return_value": "qeth",
"get_s390_subchannels.return_value": ["0.0.0900", "0.0.0901", "0.0.0902"],
"get_property.return_value": {"layer2": "1",
"portname": "FOOBAR",
"portno": "0"},
}
wired_setting = self._get_mock_objects_from_attrs([wired_setting_attrs])[0]
parent_cons_attrs = [
Expand Down

0 comments on commit 14c8d97

Please sign in to comment.