#
# Chris Lumens <clumens@redhat.com>
#
# Copyright 2005, 2006, 2007, 2008 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. 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.
#
from textwrap import dedent
from pykickstart.base import BaseData, KickstartCommand
from pykickstart.version import versionToLongString, RHEL4, RHEL5, RHEL6, RHEL7
from pykickstart.version import FC3, FC4, FC6, F8, F9, F16, F19, F20, F21, F22, F25, F27, F39
from pykickstart.constants import BOOTPROTO_BOOTP, BOOTPROTO_DHCP, BOOTPROTO_IBFT, BOOTPROTO_QUERY, BOOTPROTO_STATIC, BIND_TO_MAC
from pykickstart.options import KSOptionParser, ksboolean
from pykickstart.errors import KickstartParseError, KickstartParseWarning
import warnings
from pykickstart.i18n import _
MIN_VLAN_ID = 0
MAX_VLAN_ID = 4095
[docs]class FC3_NetworkData(BaseData):
removedKeywords = BaseData.removedKeywords
removedAttrs = BaseData.removedAttrs
def __init__(self, *args, **kwargs):
BaseData.__init__(self, *args, **kwargs)
self.bootProto = kwargs.get("bootProto", BOOTPROTO_DHCP)
self.dhcpclass = kwargs.get("dhcpclass", "")
self.device = kwargs.get("device", "")
self.essid = kwargs.get("essid", "")
self.ethtool = kwargs.get("ethtool", "")
self.gateway = kwargs.get("gateway", "")
self.hostname = kwargs.get("hostname", "")
self.ip = kwargs.get("ip", "")
self.mtu = kwargs.get("mtu", "")
self.nameserver = kwargs.get("nameserver", "")
self.netmask = kwargs.get("netmask", "")
self.nodns = kwargs.get("nodns", False)
self.onboot = kwargs.get("onboot", True)
self.wepkey = kwargs.get("wepkey", "")
def __eq__(self, y):
if not y:
return False
return self.device == y.device
def __ne__(self, y):
return not self == y
def _getArgsAsStr(self):
retval = ""
if self.bootProto:
retval += " --bootproto=%s" % self.bootProto
if self.dhcpclass:
retval += " --dhcpclass=%s" % self.dhcpclass
if self.device:
retval += " --device=%s" % self.device
if self.essid:
retval += " --essid=\"%s\"" % self.essid
if self.ethtool:
retval += " --ethtool=\"%s\"" % self.ethtool
if self.gateway:
retval += " --gateway=%s" % self.gateway
if self.hostname:
retval += " --hostname=%s" % self.hostname
if self.ip:
retval += " --ip=%s" % self.ip
if self.mtu:
retval += " --mtu=%s" % self.mtu
if self.nameserver:
retval += " --nameserver=%s" % self.nameserver
if self.netmask:
retval += " --netmask=%s" % self.netmask
if self.nodns:
retval += " --nodns"
if not self.onboot:
retval += " --onboot=off"
if self.wepkey:
retval += " --wepkey=%s" % self.wepkey
return retval
def __str__(self):
retval = BaseData.__str__(self)
retval += "network %s\n" % self._getArgsAsStr()
return retval
[docs]class FC4_NetworkData(FC3_NetworkData):
removedKeywords = FC3_NetworkData.removedKeywords
removedAttrs = FC3_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
FC3_NetworkData.__init__(self, *args, **kwargs)
self.notksdevice = kwargs.get("notksdevice", False)
def _getArgsAsStr(self):
retval = FC3_NetworkData._getArgsAsStr(self)
if self.notksdevice:
retval += " --notksdevice"
return retval
[docs]class FC6_NetworkData(FC4_NetworkData):
removedKeywords = FC4_NetworkData.removedKeywords
removedAttrs = FC4_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
FC4_NetworkData.__init__(self, *args, **kwargs)
self.noipv4 = kwargs.get("noipv4", False)
self.noipv6 = kwargs.get("noipv6", False)
def _getArgsAsStr(self):
retval = FC4_NetworkData._getArgsAsStr(self)
if self.noipv4:
retval += " --noipv4"
if self.noipv6:
retval += " --noipv6"
return retval
[docs]class F8_NetworkData(FC6_NetworkData):
removedKeywords = FC6_NetworkData.removedKeywords
removedAttrs = FC6_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
FC6_NetworkData.__init__(self, *args, **kwargs)
self.ipv6 = kwargs.get("ipv6", "")
def _getArgsAsStr(self):
retval = FC6_NetworkData._getArgsAsStr(self)
if self.ipv6:
retval += " --ipv6=%s" % self.ipv6
return retval
[docs]class F16_NetworkData(F8_NetworkData):
removedKeywords = F8_NetworkData.removedKeywords
removedAttrs = F8_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F8_NetworkData.__init__(self, *args, **kwargs)
self.activate = kwargs.get("activate", None)
self.nodefroute = kwargs.get("nodefroute", False)
self.wpakey = kwargs.get("wpakey", "")
def _getArgsAsStr(self):
retval = F8_NetworkData._getArgsAsStr(self)
if self.activate:
retval += " --activate"
if self.nodefroute:
retval += " --nodefroute"
if self.wpakey:
retval += " --wpakey=%s" % self.wpakey
return retval
[docs]class F19_NetworkData(F16_NetworkData):
removedKeywords = F16_NetworkData.removedKeywords
removedAttrs = F16_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F16_NetworkData.__init__(self, *args, **kwargs)
self.bondslaves = kwargs.get("bondslaves", "")
self.bondopts = kwargs.get("bondopts", "")
self.vlanid = kwargs.get("vlanid", "")
self.ipv6gateway = kwargs.get("ipv6gateway", "")
def _getArgsAsStr(self):
retval = F16_NetworkData._getArgsAsStr(self)
if self.bondslaves:
retval += " --bondslaves=%s" % self.bondslaves
if self.bondopts:
retval += " --bondopts=%s" % self.bondopts
if self.vlanid:
retval += " --vlanid=%s" % self.vlanid
if self.ipv6gateway:
retval += " --ipv6gateway=%s" % self.ipv6gateway
return retval
[docs]class F20_NetworkData(F19_NetworkData):
removedKeywords = F19_NetworkData.removedKeywords
removedAttrs = F19_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F19_NetworkData.__init__(self, *args, **kwargs)
self.teamslaves = kwargs.get("teamslaves", [])
self.teamconfig = kwargs.get("teamconfig", "")
def _getArgsAsStr(self):
retval = F19_NetworkData._getArgsAsStr(self)
# see the tests for format description
if self.teamslaves:
slavecfgs = []
for slave, config in self.teamslaves:
if config:
config = "'" + config + "'"
slavecfgs.append(slave + config)
slavecfgs = ",".join(slavecfgs).replace('"', r'\"')
retval += ' --teamslaves="%s"' % slavecfgs
if self.teamconfig:
retval += ' --teamconfig="%s"' % self.teamconfig.replace('"', r'\"')
return retval
[docs]class F21_NetworkData(F20_NetworkData):
removedKeywords = F20_NetworkData.removedKeywords
removedAttrs = F20_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F20_NetworkData.__init__(self, *args, **kwargs)
self.interfacename = kwargs.get("interfacename", "")
def _getArgsAsStr(self):
retval = F20_NetworkData._getArgsAsStr(self)
if self.interfacename:
retval += " --interfacename=%s" % self.interfacename
return retval
[docs]class F22_NetworkData(F21_NetworkData):
removedKeywords = F21_NetworkData.removedKeywords
removedAttrs = F21_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F21_NetworkData.__init__(self, *args, **kwargs)
self.bridgeslaves = kwargs.get("bridgeslaves", "")
self.bridgeopts = kwargs.get("bridgeopts", "")
def _getArgsAsStr(self):
retval = F21_NetworkData._getArgsAsStr(self)
if self.bridgeslaves:
retval += " --bridgeslaves=%s" % self.bridgeslaves
if self.bridgeopts:
retval += " --bridgeopts=%s" % self.bridgeopts
return retval
[docs]class F25_NetworkData(F22_NetworkData):
removedKeywords = F22_NetworkData.removedKeywords
removedAttrs = F22_NetworkData.removedAttrs
def _getArgsAsStr(self):
retval = F22_NetworkData._getArgsAsStr(self)
if self.activate == False:
retval += " --no-activate"
return retval
[docs]class F27_NetworkData(F25_NetworkData):
removedKeywords = F25_NetworkData.removedKeywords
removedAttrs = F25_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F25_NetworkData.__init__(self, *args, **kwargs)
self.bindto = kwargs.get("bindto", None)
def _getArgsAsStr(self):
retval = F25_NetworkData._getArgsAsStr(self)
if self.bindto == BIND_TO_MAC:
retval += " --bindto=%s" % self.bindto
return retval
[docs]class F39_NetworkData(F27_NetworkData):
removedKeywords = F27_NetworkData.removedKeywords
removedAttrs = F27_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F27_NetworkData.__init__(self, *args, **kwargs)
self.ipv4_dns_search = kwargs.get("ipv4_dns_search", None)
self.ipv6_dns_search = kwargs.get("ipv6_dns_search", None)
self.ipv4_ignore_auto_dns = kwargs.get("ipv4_ignore_auto_dns", None)
self.ipv6_ignore_auto_dns = kwargs.get("ipv6_ignore_auto_dns", None)
def _getArgsAsStr(self):
retval = F27_NetworkData._getArgsAsStr(self)
if self.ipv4_dns_search:
retval += " --ipv4-dns-search=%s" % self.ipv4_dns_search
if self.ipv6_dns_search:
retval += " --ipv6-dns-search=%s" % self.ipv6_dns_search
if self.ipv4_ignore_auto_dns:
retval += " --ipv4-ignore-auto-dns"
if self.ipv6_ignore_auto_dns:
retval += " --ipv6-ignore-auto-dns"
return retval
[docs]class RHEL4_NetworkData(FC3_NetworkData):
removedKeywords = FC3_NetworkData.removedKeywords
removedAttrs = FC3_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
FC3_NetworkData.__init__(self, *args, **kwargs)
self.notksdevice = kwargs.get("notksdevice", False)
def _getArgsAsStr(self):
retval = FC3_NetworkData._getArgsAsStr(self)
if self.notksdevice:
retval += " --notksdevice"
return retval
[docs]class RHEL6_NetworkData(F8_NetworkData):
removedKeywords = F8_NetworkData.removedKeywords
removedAttrs = F8_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F8_NetworkData.__init__(self, *args, **kwargs)
self.activate = kwargs.get("activate", None)
self.nodefroute = kwargs.get("nodefroute", False)
self.vlanid = kwargs.get("vlanid", "")
self.bondslaves = kwargs.get("bondslaves", "")
self.bondopts = kwargs.get("bondopts", "")
def _getArgsAsStr(self):
retval = F8_NetworkData._getArgsAsStr(self)
if self.activate:
retval += " --activate"
if self.nodefroute:
retval += " --nodefroute"
if self.vlanid:
retval += " --vlanid=%s" % self.vlanid
if self.bondslaves:
retval += " --bondslaves=%s" % self.bondslaves
if self.bondopts:
retval += " --bondopts=%s" % self.bondopts
return retval
[docs]class RHEL7_NetworkData(F21_NetworkData):
removedKeywords = F21_NetworkData.removedKeywords
removedAttrs = F21_NetworkData.removedAttrs
def __init__(self, *args, **kwargs):
F21_NetworkData.__init__(self, *args, **kwargs)
self.bridgeslaves = kwargs.get("bridgeslaves", "")
self.bridgeopts = kwargs.get("bridgeopts", "")
self.bindto = kwargs.get("bindto", None)
def _getArgsAsStr(self):
retval = F21_NetworkData._getArgsAsStr(self)
if self.bridgeslaves:
retval += " --bridgeslaves=%s" % self.bridgeslaves
if self.bridgeopts:
retval += " --bridgeopts=%s" % self.bridgeopts
if self.activate == False:
retval += " --no-activate"
if self.bindto == BIND_TO_MAC:
retval += " --bindto=%s" % self.bindto
return retval
[docs]class FC3_Network(KickstartCommand):
removedKeywords = KickstartCommand.removedKeywords
removedAttrs = KickstartCommand.removedAttrs
def __init__(self, writePriority=0, *args, **kwargs):
KickstartCommand.__init__(self, writePriority, *args, **kwargs)
self.bootprotoList = [BOOTPROTO_DHCP, BOOTPROTO_BOOTP,
BOOTPROTO_STATIC]
self.op = self._getParser()
self.network = kwargs.get("network", [])
def __str__(self):
retval = ""
for nic in self.network:
retval += nic.__str__()
if retval:
return "# Network information\n" + retval
else:
return ""
def _getParser(self):
op = KSOptionParser(prog="network", description="""
Configures network information for target system
and activates network devices in installer
environment. The device specified in the first
network command is activated automatically.
Activation of the device can be also explicitly
required by ``--activate`` option""", version=FC3)
op.add_argument("--bootproto", dest="bootProto", version=FC3,
default=BOOTPROTO_DHCP, choices=self.bootprotoList,
help="""
The method of IPv4 configuration. For IPv6
configuration use ``--ipv6`` option.
The default setting is ``dhcp``. To turn IPv4
configuration off use ``--noipv4`` option.
- The ``dhcp`` method uses a DHCP server system to obtain its networking configuration.
- The ``static`` method requires that you specify at least IP address and netmask with ``--ip`` and ``--netmask`` options.
For example::
``network --device=link --bootproto=static --ip=10.0.2.15 --netmask=255.255.255.0 --gateway=10.0.2.254 --nameserver=10.0.2.1``
- ``ibft`` setting is for reading the configuration from iBFT table.""")
op.add_argument("--dhcpclass", version=FC3, help="""
Specifies the DHCP vendor class identifier. The dhcpd
service will see this value as vendor-class-identifier.""")
op.add_argument("--device", version=FC3, help="""
Specifies the device to be configured (and eventually
activated in Anaconda) with the network command.
You can specify a device to be activated in any of the following ways:
- the device name of the interface, for example, ``em1``
- the MAC address of the interface, for example, ``01:23:45:67:89:ab``
- the keyword ``link``, which specifies the first interface with its link in the up state
- the keyword ``bootif``, which uses the MAC address that pxelinux set in the ``BOOTIF`` variable. Set ``IPAPPEND 2`` in your pxelinux.cfg file to have pxelinux set the ``BOOTIF`` variable.
For example::
``network --bootproto=dhcp --device=ens3``
If the ``--device=`` option is missing on the first use
of the network command, the value of the ``ksdevice=``
Anaconda boot option is used, if available. If
``ksdevice=`` is not set, ``link`` value is used. Note
that this is considered deprecated behavior; in most
cases, you should always specify a ``--device=`` for
every network command. The behavior of any subsequent
network command in the same Kickstart file is
unspecified if its ``--device=`` option is missing.
Make sure you specify this option for any network
command beyond the first.
""")
op.add_argument("--essid", version=FC3,
help="The network ID for wireless networks.")
op.add_argument("--ethtool", version=FC3, help="""
Specifies additional low-level settings for the network
device which will be passed to the ethtool program.""")
op.add_argument("--gateway", version=FC3,
help="Default gateway, as a single IPv4 address.")
op.add_argument("--hostname", version=FC3,
help="""
The host name for the installed system.
The host name can either be a fully-qualified domain
name (FQDN) in the format hostname.domainname, or a
short host name with no domain. Many networks have a
DHCP service which automatically supplies connected
systems with a domain name; to allow DHCP to assign the
domain name, only specify a short host name.""")
op.add_argument("--ip", version=FC3,
help="IPv4 address for the interface.")
op.add_argument("--mtu", version=FC3, help="The MTU of the device.")
op.add_argument("--nameserver", version=FC3, help="""
Primary nameserver, as an IP address. Multiple
nameservers must be comma separated.""")
op.add_argument("--netmask", version=FC3,
help="IPv4 network mask of the device.")
op.add_argument("--nodns", action="store_true", default=False,
version=FC3, help="Do not configure any DNS server.")
op.add_argument("--onboot", type=ksboolean, version=FC3, help="""
Whether or not to enable the device a boot time.""")
op.add_argument("--wepkey", version=FC3,
help="The WEP encryption key for wireless networks.")
return op
[docs] def parse(self, args):
ns = self.op.parse_args(args=args, lineno=self.lineno)
nd = self.dataClass() # pylint: disable=not-callable
self.set_to_obj(ns, nd)
nd.lineno = self.lineno
# Check for duplicates in the data list.
if nd in self.dataList():
warnings.warn(_("A network device with the name %s has already been defined.") % nd.device, KickstartParseWarning)
return nd
[docs] def dataList(self):
return self.network
@property
def dataClass(self):
return self.handler.NetworkData
[docs]class FC4_Network(FC3_Network):
removedKeywords = FC3_Network.removedKeywords
removedAttrs = FC3_Network.removedAttrs
def _getParser(self):
op = FC3_Network._getParser(self)
op.add_argument("--notksdevice", action="store_true", default=False,
version=FC4, help="""
This network device is not used for kickstart.""")
return op
[docs]class FC6_Network(FC4_Network):
removedKeywords = FC4_Network.removedKeywords
removedAttrs = FC4_Network.removedAttrs
def _getParser(self):
op = FC4_Network._getParser(self)
op.add_argument("--noipv4", action="store_true", default=False,
version=FC6, help="Disable IPv4 configuration of this device.")
op.add_argument("--noipv6", action="store_true", default=False,
version=FC6, help="Disable IPv6 configuration of this device.")
return op
[docs]class F8_Network(FC6_Network):
removedKeywords = FC6_Network.removedKeywords
removedAttrs = FC6_Network.removedAttrs
def _getParser(self):
op = FC6_Network._getParser(self)
op.add_argument("--ipv6", version=F8, help="""
IPv6 address for the interface. This can be:
- the static address in form ``<IPv6 address>[/<prefix length>]``, e.g. ``3ffe:ffff:0:1::1/128`` (if prefix is omitted 64 is assumed),
- ``auto`` for stateless automatic address autoconfiguration, or
- ``dhcp`` for DHCPv6-only configuration (no router advertisements).
""")
return op
[docs]class F9_Network(F8_Network):
removedKeywords = F8_Network.removedKeywords
removedAttrs = F8_Network.removedAttrs
def __init__(self, writePriority=0, *args, **kwargs):
F8_Network.__init__(self, writePriority, *args, **kwargs)
self.bootprotoList.append(BOOTPROTO_QUERY)
def _getParser(self):
op = F8_Network._getParser(self)
for action in op._actions:
if "--bootproto" in action.option_strings:
action.help += dedent("""
.. versionchanged:: %s
The 'query' value was added.""" % versionToLongString(F9))
break
return op
[docs]class F16_Network(F9_Network):
removedKeywords = F9_Network.removedKeywords
removedAttrs = F9_Network.removedAttrs
def __init__(self, writePriority=0, *args, **kwargs):
F9_Network.__init__(self, writePriority, *args, **kwargs)
self.bootprotoList.append(BOOTPROTO_IBFT)
def _getParser(self):
op = F9_Network._getParser(self)
for action in op._actions:
if "--bootproto" in action.option_strings:
action.help += dedent("""
.. versionchanged:: %s
The 'ibft' value was added.""" % versionToLongString(F16))
break
op.add_argument("--activate", action="store_true", version=F16,
default=None, help="""
As noted above, using this option ensures any matching
devices beyond the first will also be activated.""")
op.add_argument("--nodefroute", action="store_true", version=F16,
default=False, help="""
Prevents grabbing of the default route by the device.
It can be useful when activating additional devices in
installer using ``--activate`` option.""")
op.add_argument("--wpakey", default="", version=F16, help="""
The WPA encryption key for wireless networks.""")
return op
[docs]class F18_Network(F16_Network):
@property
def hostname(self):
for nd in self.dataList():
if nd.hostname:
return nd.hostname
return None
[docs]class F19_Network(F18_Network):
def _getParser(self):
op = F18_Network._getParser(self)
op.add_argument("--bondslaves", default="", version=F19, help="""
Bonded device with name specified by ``--device`` option
will be created using slaves specified in this option.
Example::
``network --device bond0 --bootproto static --ip=10.34.102.222 --netmask=255.255.255.0 --gateway=10.34.102.254 --nameserver=10.34.39.2 --bondslaves=ens7,ens8 --bondopts=mode=active-backup,primary=ens7 --activate``
""")
op.add_argument("--bondopts", default="", version=F19, help="""
A comma-separated list of optional parameters for bonded
interface specified by ``--bondslaves`` and ``--device``
options. Example::
``--bondopts=mode=active-backup,primary=eth1``
If an option itself contains comma as separator use
semicolon to separate the options. Example::
``--bondopts=mode=active-backup,balance-rr;primary=eth1``
""")
op.add_argument("--vlanid", version=F19, help="""
Id (802.1q tag) of vlan device to be created using parent
device specified by ``--device`` option. For example::
``network --device=eth0 --vlanid=171``
will create vlan device ``eth0.171``.""")
op.add_argument("--ipv6gateway", default="", version=F19, help="""
Default gateway, as a single IPv6 address.
""")
return op
[docs]class F20_Network(F19_Network):
def _getParser(self):
# see the tests for teamslaves option
def teamslaves_cb(value):
# value is of: "<DEV1>['<JSON_CONFIG1>'],<DEV2>['<JSON_CONFIG2>'],..."
# for example: "eth1,eth2'{"prio": 100}',eth3"
teamslaves = []
if value:
# Although slaves, having optional config, are separated by ","
# first extract json configs because they can contain the ","
parts = value.split("'")
# parts == ['eth1,eth2', '{"prio": 100}', ',eth3']
# ensure the list has even number of items for further zipping,
# for odd number of items
if len(parts) % 2 == 1:
# if the list ends with an empty string which must be a leftover
# from splitting string not ending with device eg
# "eth1,eth2'{"prio":100}'"
if not parts[-1]:
# just remove it
parts = parts[:-1]
# if not (our example), add empty config for the last device
else:
parts.append('')
# parts == ['eth1,eth2', '{"prio": 100}', ',eth3', '']
# zip devices with their configs
it = iter(parts)
for devs, cfg in zip(it, it):
# first loop:
# devs == "eth1,eth2", cfg == '{"prio": 100}'
devs = devs.strip(',').split(',')
# devs == ["eth1", "eth2"]
# initialize config of all devs but the last one to empty
for d in devs[:-1]:
teamslaves.append((d, ''))
# teamslaves == [("eth1", '')]
# and set config of the last device
teamslaves.append((devs[-1], cfg))
# teamslaves == [('eth1', ''), ('eth2', '{"prio": 100}']
return teamslaves
op = F19_Network._getParser(self)
op.add_argument("--teamslaves", type=teamslaves_cb, version=F20,
help="""
Team device with name specified by ``--device`` option
will be created using slaves specified in this option.
Slaves are separated by comma. A slave can be followed
by its configuration which is a single-quoted json format
string with double qoutes escaped by ``'\'`` character.
Example::
``--teamslaves="p3p1'{\"prio\": -10, \"sticky\": true}',p3p2'{\"prio\": 100}'"``.
See also ``--teamconfig`` option.""")
op.add_argument("--teamconfig", default="", version=F20, help="""
Double-quoted team device configuration which is a json
format string with double quotes escaped with ``'\'``
character. The device name is specified by ``--device``
option and its slaves and their configuration by
``--teamslaves`` option. Example::
``network --device team0 --activate --bootproto static --ip=10.34.102.222 --netmask=255.255.255.0 --gateway=10.34.102.254 --nameserver=10.34.39.2 --teamslaves="p3p1'{\"prio\": -10, \"sticky\": true}',p3p2'{\"prio\": 100}'" --teamconfig="{\"runner\": {\"name\": \"activebackup\"}}"``
""")
return op
[docs]class F21_Network(F20_Network):
def _getParser(self):
op = F20_Network._getParser(self)
op.add_argument("--interfacename", default="", version=F21, help="""
Specify a custom interface name for a virtual LAN
device. This option should be used when the default
name generated by the ``--vlanid=`` option is not
desirable. This option must be used along with
``--vlanid=``. For example::
``network --device=em1 --vlanid=171 --interfacename=vlan171``
The above command creates a virtual LAN interface named
``vlan171`` on the em1 device with an ID of 171. The
interface name can be arbitrary (for example,
``my-vlan``), but in specific cases, the following
conventions must be followed:
If the name contains a dot (.), it must take the form
of NAME.ID. The NAME is arbitrary, but the ID must be
the VLAN ID. For example: ``em1.171`` or
``my-vlan.171``. Names starting with vlan must take
the form of vlanID - for example: ``vlan171``.""")
return op
[docs]class F22_Network(F21_Network):
def _getParser(self):
op = F21_Network._getParser(self)
op.add_argument("--bridgeslaves", default="", version=F22, help="""
When this option is used, the network bridge with
device name specified using the ``--device=`` option
will be created and devices defined in the
``--bridgeslaves=`` option will be added to the bridge.
For example::
``network --device=bridge0 --bridgeslaves=em1``""")
op.add_argument("--bridgeopts", default="", version=F22, help="""
An optional comma-separated list of parameters for the
bridged interface. Available values are ``stp``,
``priority``, ``forward-delay``, ``hello-time``,
``max-age``, and ``ageing-time``. For information about
these parameters, see the bridge setting table in the
nm-settings(5) man page or at
https://developer.gnome.org/NetworkManager/0.9/ref-settings.html.
""")
return op
[docs] def parse(self, args):
# call the overridden command to do it's job first
retval = F21_Network.parse(self, args)
if retval.bridgeopts:
if not retval.bridgeslaves:
msg = _("Option --bridgeopts requires --bridgeslaves to be specified")
raise KickstartParseError(msg, lineno=self.lineno)
opts = retval.bridgeopts.split(",")
for opt in opts:
_key, _sep, value = opt.partition("=")
if not value or "=" in value:
msg = _("Bad format of --bridgeopts, expecting key=value options separated by ','")
raise KickstartParseError(msg, lineno=self.lineno)
return retval
[docs]class F24_Network(F22_Network):
removedKeywords = F22_Network.removedKeywords
removedAttrs = F22_Network.removedAttrs
[docs] def parse(self, args):
retval = F22_Network.parse(self, args)
# If we specify noipv4 then we need to make sure bootproto is zero'ed
# out
if retval.noipv4:
retval.bootProto = ""
return retval
[docs]class F25_Network(F24_Network):
removedKeywords = F24_Network.removedKeywords
removedAttrs = F24_Network.removedAttrs
def _getParser(self):
op = F24_Network._getParser(self)
op.add_argument("--no-activate", default=None, version=F25, dest="activate",
action="store_false", help="""
Use this option with first network command to prevent
activation of the device in istaller environment""")
return op
[docs]class F27_Network(F25_Network):
removedKeywords = F25_Network.removedKeywords
removedAttrs = F25_Network.removedAttrs
def __init__(self, writePriority=0, *args, **kwargs):
self.bind_to_choices = [BIND_TO_MAC]
F25_Network.__init__(self, writePriority, *args, **kwargs)
def _getParser(self):
op = F25_Network._getParser(self)
op.add_argument("--bindto", dest="bindto", default=None, version=F27,
choices=self.bind_to_choices, help="""
Optionally allows to specify how the connection
configuration created for the device should be bound. If
the option is not used, the connection binds to
interface name (``DEVICE`` value in ifcfg file). For
virtual devices (bond, team, bridge) it configures
binding of slaves. Not applicable to vlan devices.
Note that this option is independent of how the
``--device`` is specified.
Currently only the value ``mac`` is suported.
``--bindto=mac`` will bind the connection to MAC address
of the device (``HWADDR`` value in ifcfg file).
For example::
``network --device=01:23:45:67:89:ab --bootproto=dhcp --bindto=mac``
will bind the configuration of the device specified by
MAC address ``01:23:45:67:89:ab`` to its MAC address.
``network --device=01:23:45:67:89:ab --bootproto=dhcp``
will bind the configuration of the device specified by
MAC address ``01:23:45:67:89:ab`` to its interface name
(eg ``ens3``).
``network --device=ens3 --bootproto=dhcp --bindto=mac``
will bind the configuration of the device specified by
interface name ``ens3`` to its MAC address.
""")
return op
[docs] def parse(self, args):
# call the overridden command to do it's job first
retval = F25_Network.parse(self, args)
if retval.bindto == BIND_TO_MAC:
if retval.vlanid and not retval.bondopts:
msg = _("--bindto=%s is not supported for this type of device") % BIND_TO_MAC
raise KickstartParseError(msg, lineno=self.lineno)
return retval
[docs]class F39_Network(F27_Network):
removedKeywords = F27_Network.removedKeywords
removedAttrs = F27_Network.removedAttrs
def _getParser(self):
op = F27_Network._getParser(self)
op.add_argument("--ipv4-dns-search", default=None, version=F39, dest="ipv4_dns_search",
help="""
Use this option to set IPv4 search domains. For example: ``--ipv4-dns-search domain1.example.com,domain2.example.com``
Requires ``--device`` to be specified.""")
op.add_argument("--ipv6-dns-search", default=None, version=F39, dest="ipv6_dns_search",
help="""
Use this option to set IPv6 search domains. For example: ``--ipv6-dns-search domain1.example.com,domain2.example.com``
Requires ``--device`` to be specified.""")
op.add_argument("--ipv4-ignore-auto-dns", action="store_true", version=F39,
dest="ipv4_ignore_auto_dns", help="""
Use this option to ignore IPv4 automatic DNS.
Requires ``--device`` to be specified.""")
op.add_argument("--ipv6-ignore-auto-dns", action="store_true", version=F39,
dest="ipv6_ignore_auto_dns", help="""
Use this option to ignore IPv6 automatic DNS.
Requires ``--device`` to be specified.""")
return op
[docs] def parse(self, args):
retval = F27_Network.parse(self, args)
if not retval.device:
if retval.ipv4_dns_search:
msg = _("Option --ipv4-dns-search requires --device to be specified")
raise KickstartParseError(msg, lineno=self.lineno)
if retval.ipv6_dns_search:
msg = _("Option --ipv6-dns-search requires --device to be specified")
raise KickstartParseError(msg, lineno=self.lineno)
if retval.ipv4_ignore_auto_dns:
msg = _("Option --ipv4-ignore-auto-dns requires --device to be specified")
raise KickstartParseError(msg, lineno=self.lineno)
if retval.ipv6_ignore_auto_dns:
msg = _("Option --ipv6-ignore-auto-dns requires --device to be specified")
raise KickstartParseError(msg, lineno=self.lineno)
return retval
[docs]class RHEL4_Network(FC3_Network):
removedKeywords = FC3_Network.removedKeywords
removedAttrs = FC3_Network.removedAttrs
def _getParser(self):
op = FC3_Network._getParser(self)
op.add_argument("--notksdevice", action="store_true", default=False,
version=RHEL4, help="This network device is not used for kickstart.")
return op
[docs]class RHEL5_Network(FC6_Network):
removedKeywords = FC6_Network.removedKeywords
removedAttrs = FC6_Network.removedAttrs
def __init__(self, writePriority=0, *args, **kwargs):
FC6_Network.__init__(self, writePriority, *args, **kwargs)
self.bootprotoList.append(BOOTPROTO_QUERY)
def _getParser(self):
op = FC6_Network._getParser(self)
for action in op._actions:
if "--bootproto" in action.option_strings:
action.help += dedent("""
.. versionchanged:: %s
The 'query' value was added.""" % versionToLongString(RHEL5))
break
return op
[docs]class RHEL6_Network(F9_Network):
removedKeywords = F9_Network.removedKeywords
removedAttrs = F9_Network.removedAttrs
def __init__(self, writePriority=0, *args, **kwargs):
F9_Network.__init__(self, writePriority, *args, **kwargs)
self.bootprotoList.append(BOOTPROTO_IBFT)
def _getParser(self):
op = F9_Network._getParser(self)
for action in op._actions:
if "--bootproto" in action.option_strings:
action.help += dedent("""
.. versionchanged:: %s
The 'ibft' value was added.""" % versionToLongString(RHEL6))
break
op.add_argument("--activate", action="store_true", version=RHEL6,
default=None, help="""
Activate this device in the installation environment.
If the device has already been activated (for example,
an interface you configured with boot options so that
the system could retrieve the Kickstart file) the
device is reactivated to use the configuration
specified in the Kickstart file.""")
op.add_argument("--nodefroute", action="store_true", version=RHEL6,
default=False, help="""
Prevents the interface being set as the default route.
Use this option when you activate additional devices
with the ``--activate=`` option, for example, a NIC on
a separate subnet for an iSCSI target.""")
op.add_argument("--vlanid", version=RHEL6, help="""
Id (802.1q tag) of vlan device to be created using parent
device specified by ``--device`` option. For example::
``network --device=eth0 --vlanid=171``
will create vlan device ``eth0.171``.""")
op.add_argument("--bondslaves", version=RHEL6, help="""
Bonded device with name specified by ``--device`` option
will be created using slaves specified in this option.
Example::
``network --device bond0 --bootproto static --ip=10.34.102.222 --netmask=255.255.255.0 --gateway=10.34.102.254 --nameserver=10.34.39.2 --bondslaves=eth0,eth1 --bondopts=mode=active-backup,primary=eth0 --activate``
""")
op.add_argument("--bondopts", version=RHEL6, help="""
A comma-separated list of optional parameters for bonded
interface specified by ``--bondslaves`` and ``--device``
options. Example::
``--bondopts=mode=active-backup,primary=eth1``
If an option itself contains comma as separator use
semicolon to separate the options. Example::
``--bondopts=mode=active-backup,balance-rr;primary=eth1``
""")
return op
[docs]def validate_network_interface_name(name):
"""Check if the given network interface name is valid, return an error message
if an error is found or None if no errors are found
:param str name: name to validate
:returns: error message or None if no error is found
:rtype: str or NoneType
"""
# (for reference see the NetworkManager source code:
# NetworkManager/src/settings/plugins/ifcfg-rh/reader.c
# and the make_vlan_setting function)
vlan_id = None
# if it contains '.', vlan id should follow (eg 'ens7.171', 'mydev.171')
(vlan, dot, id_candidate) = name.partition(".")
if dot:
# 'vlan' can't be followed by a '.'
if vlan == "vlan":
return _("When using the <prefix>.<vlan id> interface name notation, <prefix> can't be equal to 'vlan'.")
try:
vlan_id = int(id_candidate)
except ValueError:
return _("If network --interfacename contains a '.', valid vlan id should follow.")
# if it starts with 'vlan', vlan id should follow ('vlan171')
(empty, sep, id_candidate) = name.partition("vlan")
if sep and empty == "":
# if we checked only for empty == "", we would evaluate missing interface name as an error
try:
vlan_id = int(id_candidate)
except ValueError:
return _("If network --interfacename starts with 'vlan', valid vlan id should follow.")
# check if the vlan id is in range
if vlan_id is not None:
if not(MIN_VLAN_ID <= vlan_id <= MAX_VLAN_ID):
return _("The vlan id is out of the %(minimum)d-%(maximum)d vlan id range.") % {"minimum": MIN_VLAN_ID, "maximum": MAX_VLAN_ID}
# network interface name seems to be valid (no error found)
return None
[docs]class RHEL7_Network(F21_Network):
def __init__(self, writePriority=0, *args, **kwargs):
self.bind_to_choices = [BIND_TO_MAC]
F21_Network.__init__(self, writePriority, *args, **kwargs)
def _getParser(self):
op = F21_Network._getParser(self)
op.add_argument("--bridgeslaves", default="", version=RHEL7, help="""
When this option is used, the network bridge with
device name specified using the ``--device=`` option
will be created and devices defined in the
``--bridgeslaves=`` option will be added to the bridge.
For example::
``network --device=bridge0 --bridgeslaves=em1``""")
op.add_argument("--bridgeopts", default="", version=RHEL7, help="""
An optional comma-separated list of parameters for the
bridged interface. Available values are ``stp``,
``priority``, ``forward-delay``, ``hello-time``,
``max-age``, and ``ageing-time``. For information about
these parameters, see the bridge setting table in the
nm-settings(5) man page or at
https://developer.gnome.org/NetworkManager/0.9/ref-settings.html.
""")
op.add_argument("--no-activate", default=None, version=RHEL7, dest="activate",
action="store_false", help="""
Use this option with first network command to prevent
activation of the device in istaller environment""")
op.add_argument("--bindto", dest="bindto", default=None, version=RHEL7,
choices=self.bind_to_choices, help="""
Optionally allows to specify how the connection
configuration created for the device should be bound. If
the option is not used, the connection binds to
interface name (``DEVICE`` value in ifcfg file). For
virtual devices (bond, team, bridge) it configures
binding of slaves. Not applicable to vlan devices.
Note that this option is independent of how the
``--device`` is specified.
Currently only the value ``mac`` is suported.
``--bindto=mac`` will bind the connection to MAC address
of the device (``HWADDR`` value in ifcfg file).
For example::
``network --device=01:23:45:67:89:ab --bootproto=dhcp --bindto=mac``
will bind the configuration of the device specified by
MAC address ``01:23:45:67:89:ab`` to its MAC address.
``network --device=01:23:45:67:89:ab --bootproto=dhcp``
will bind the configuration of the device specified by
MAC address ``01:23:45:67:89:ab`` to its interface name
(eg ``ens3``).
``network --device=ens3 --bootproto=dhcp --bindto=mac``
will bind the configuration of the device specified by
interface name ``ens3`` to its MAC address.
""")
return op
[docs] def parse(self, args):
# call the overridden command to do it's job first
retval = F21_Network.parse(self, args)
# validate the network interface name
error_message = validate_network_interface_name(retval.interfacename)
# something is wrong with the interface name
if error_message:
raise KickstartParseError(error_message, lineno=self.lineno)
if retval.bridgeopts:
if not retval.bridgeslaves:
msg = _("Option --bridgeopts requires --bridgeslaves to be specified")
raise KickstartParseError(msg, lineno=self.lineno)
opts = retval.bridgeopts.split(",")
for opt in opts:
_key, _sep, value = opt.partition("=")
if not value or "=" in value:
msg = _("Bad format of --bridgeopts, expecting key=value options separated by ','")
raise KickstartParseError(msg, lineno=self.lineno)
if retval.bindto == BIND_TO_MAC:
if retval.vlanid and not retval.bondopts:
msg = _("--bindto=%s is not supported for this type of device") % BIND_TO_MAC
raise KickstartParseError(msg, lineno=self.lineno)
return retval