2 # Chris Lumens <clumens@redhat.com>
4 # Copyright 2005, 2006, 2007, 2008 Red Hat, Inc.
6 # This copyrighted material is made available to anyone wishing to use, modify,
7 # copy, or redistribute it subject to the terms and conditions of the GNU
8 # General Public License v.2. This program is distributed in the hope that it
9 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
10 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # See the GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 51
15 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
16 # trademarks that are incorporated in the source code or documentation are not
17 # subject to the GNU General Public License and may only be used or replicated
18 # with the express permission of Red Hat, Inc.
20 from pykickstart
.base
import BaseData
, KickstartCommand
21 from pykickstart
.constants
import BOOTPROTO_BOOTP
, BOOTPROTO_DHCP
, BOOTPROTO_IBFT
, BOOTPROTO_QUERY
, BOOTPROTO_STATIC
22 from pykickstart
.options
import KSOptionParser
26 _
= lambda x
: gettext
.ldgettext("pykickstart", x
)
31 class FC3_NetworkData(BaseData
):
32 removedKeywords
= BaseData
.removedKeywords
33 removedAttrs
= BaseData
.removedAttrs
35 def __init__(self
, *args
, **kwargs
):
36 BaseData
.__init
__(self
, *args
, **kwargs
)
37 self
.bootProto
= kwargs
.get("bootProto", BOOTPROTO_DHCP
)
38 self
.dhcpclass
= kwargs
.get("dhcpclass", "")
39 self
.device
= kwargs
.get("device", "")
40 self
.essid
= kwargs
.get("essid", "")
41 self
.ethtool
= kwargs
.get("ethtool", "")
42 self
.gateway
= kwargs
.get("gateway", "")
43 self
.hostname
= kwargs
.get("hostname", "")
44 self
.ip
= kwargs
.get("ip", "")
45 self
.mtu
= kwargs
.get("mtu", "")
46 self
.nameserver
= kwargs
.get("nameserver", "")
47 self
.netmask
= kwargs
.get("netmask", "")
48 self
.nodns
= kwargs
.get("nodns", False)
49 self
.onboot
= kwargs
.get("onboot", True)
50 self
.wepkey
= kwargs
.get("wepkey", "")
56 return self
.device
and self
.device
== y
.device
61 def _getArgsAsStr(self
):
64 if self
.bootProto
!= "":
65 retval
+= " --bootproto=%s" % self
.bootProto
66 if self
.dhcpclass
!= "":
67 retval
+= " --dhcpclass=%s" % self
.dhcpclass
69 retval
+= " --device=%s" % self
.device
71 retval
+= " --essid=\"%s\"" % self
.essid
72 if self
.ethtool
!= "":
73 retval
+= " --ethtool=\"%s\"" % self
.ethtool
74 if self
.gateway
!= "":
75 retval
+= " --gateway=%s" % self
.gateway
76 if self
.hostname
!= "":
77 retval
+= " --hostname=%s" % self
.hostname
79 retval
+= " --ip=%s" % self
.ip
81 retval
+= " --mtu=%s" % self
.mtu
82 if self
.nameserver
!= "":
83 retval
+= " --nameserver=%s" % self
.nameserver
84 if self
.netmask
!= "":
85 retval
+= " --netmask=%s" % self
.netmask
89 retval
+= " --onboot=off"
91 retval
+= " --wepkey=%s" % self
.wepkey
96 retval
= BaseData
.__str
__(self
)
97 retval
+= "network %s\n" % self
._getArgsAsStr
()
100 class FC4_NetworkData(FC3_NetworkData
):
101 removedKeywords
= FC3_NetworkData
.removedKeywords
102 removedAttrs
= FC3_NetworkData
.removedAttrs
104 def __init__(self
, *args
, **kwargs
):
105 FC3_NetworkData
.__init
__(self
, *args
, **kwargs
)
106 self
.notksdevice
= kwargs
.get("notksdevice", False)
108 def _getArgsAsStr(self
):
109 retval
= FC3_NetworkData
._getArgsAsStr
(self
)
112 retval
+= " --notksdevice"
116 class FC6_NetworkData(FC4_NetworkData
):
117 removedKeywords
= FC4_NetworkData
.removedKeywords
118 removedAttrs
= FC4_NetworkData
.removedAttrs
120 def __init__(self
, *args
, **kwargs
):
121 FC4_NetworkData
.__init
__(self
, *args
, **kwargs
)
122 self
.noipv4
= kwargs
.get("noipv4", False)
123 self
.noipv6
= kwargs
.get("noipv6", False)
125 def _getArgsAsStr(self
):
126 retval
= FC4_NetworkData
._getArgsAsStr
(self
)
129 retval
+= " --noipv4"
131 retval
+= " --noipv6"
135 class F8_NetworkData(FC6_NetworkData
):
136 removedKeywords
= FC6_NetworkData
.removedKeywords
137 removedAttrs
= FC6_NetworkData
.removedAttrs
139 def __init__(self
, *args
, **kwargs
):
140 FC6_NetworkData
.__init
__(self
, *args
, **kwargs
)
141 self
.ipv6
= kwargs
.get("ipv6", "")
143 def _getArgsAsStr(self
):
144 retval
= FC6_NetworkData
._getArgsAsStr
(self
)
147 retval
+= " --ipv6=%s" % self
.ipv6
151 class F16_NetworkData(F8_NetworkData
):
152 removedKeywords
= F8_NetworkData
.removedKeywords
153 removedAttrs
= F8_NetworkData
.removedAttrs
155 def __init__(self
, *args
, **kwargs
):
156 F8_NetworkData
.__init
__(self
, *args
, **kwargs
)
157 self
.activate
= kwargs
.get("activate", False)
158 self
.nodefroute
= kwargs
.get("nodefroute", False)
159 self
.wpakey
= kwargs
.get("wpakey", "")
161 def _getArgsAsStr(self
):
162 retval
= F8_NetworkData
._getArgsAsStr
(self
)
165 retval
+= " --activate"
167 retval
+= " --nodefroute"
168 if self
.wpakey
!= "":
169 retval
+= " --wpakey=%s" % self
.wpakey
173 class F19_NetworkData(F16_NetworkData
):
174 removedKeywords
= F16_NetworkData
.removedKeywords
175 removedAttrs
= F16_NetworkData
.removedAttrs
177 def __init__(self
, *args
, **kwargs
):
178 F16_NetworkData
.__init
__(self
, *args
, **kwargs
)
179 self
.bondslaves
= kwargs
.get("bondslaves", "")
180 self
.bondopts
= kwargs
.get("bondopts", "")
181 self
.vlanid
= kwargs
.get("vlanid", "")
182 self
.ipv6gateway
= kwargs
.get("ipv6gateway", "")
184 def _getArgsAsStr(self
):
185 retval
= F16_NetworkData
._getArgsAsStr
(self
)
187 if self
.bondslaves
!= "":
188 retval
+= " --bondslaves=%s" % self
.bondslaves
189 if self
.bondopts
!= "":
190 retval
+= " --bondopts=%s" % self
.bondopts
192 retval
+= " --vlanid %s" % self
.vlanid
194 retval
+= " --ipv6gateway %s" % self
.ipv6gateway
198 class F20_NetworkData(F19_NetworkData
):
199 removedKeywords
= F19_NetworkData
.removedKeywords
200 removedAttrs
= F19_NetworkData
.removedAttrs
202 def __init__(self
, *args
, **kwargs
):
203 F19_NetworkData
.__init
__(self
, *args
, **kwargs
)
204 self
.teamslaves
= kwargs
.get("teamslaves", [])
205 self
.teamconfig
= kwargs
.get("teamconfig", "")
207 def _getArgsAsStr(self
):
208 retval
= F19_NetworkData
._getArgsAsStr
(self
)
210 # see the tests for format description
213 for slave
, config
in self
.teamslaves
:
215 config
= "'" + config
+ "'"
216 slavecfgs
.append(slave
+config
)
217 slavecfgs
= ",".join(slavecfgs
).replace('"', r
'\"')
218 retval
+= ' --teamslaves="%s"' % slavecfgs
220 retval
+= ' --teamconfig="%s"' % self
.teamconfig
.replace('"', r
'\"')
223 class F21_NetworkData(F20_NetworkData
):
224 removedKeywords
= F20_NetworkData
.removedKeywords
225 removedAttrs
= F20_NetworkData
.removedAttrs
227 def __init__(self
, *args
, **kwargs
):
228 F20_NetworkData
.__init
__(self
, *args
, **kwargs
)
229 self
.interfacename
= kwargs
.get("interfacename", "")
231 def _getArgsAsStr(self
):
232 retval
= F20_NetworkData
._getArgsAsStr
(self
)
233 if self
.interfacename
:
234 retval
+= " --interfacename=%s" % self
.interfacename
238 class RHEL4_NetworkData(FC3_NetworkData
):
239 removedKeywords
= FC3_NetworkData
.removedKeywords
240 removedAttrs
= FC3_NetworkData
.removedAttrs
242 def __init__(self
, *args
, **kwargs
):
243 FC3_NetworkData
.__init
__(self
, *args
, **kwargs
)
244 self
.notksdevice
= kwargs
.get("notksdevice", False)
246 def _getArgsAsStr(self
):
247 retval
= FC3_NetworkData
._getArgsAsStr
(self
)
250 retval
+= " --notksdevice"
254 class RHEL6_NetworkData(F8_NetworkData
):
255 removedKeywords
= F8_NetworkData
.removedKeywords
256 removedAttrs
= F8_NetworkData
.removedAttrs
258 def __init__(self
, *args
, **kwargs
):
259 F8_NetworkData
.__init
__(self
, *args
, **kwargs
)
260 self
.activate
= kwargs
.get("activate", False)
261 self
.nodefroute
= kwargs
.get("nodefroute", False)
262 self
.vlanid
= kwargs
.get("vlanid", "")
263 self
.bondslaves
= kwargs
.get("bondslaves", "")
264 self
.bondopts
= kwargs
.get("bondopts", "")
266 def _getArgsAsStr(self
):
267 retval
= F8_NetworkData
._getArgsAsStr
(self
)
270 retval
+= " --activate"
272 retval
+= " --nodefroute"
274 retval
+= " --vlanid %s" % self
.vlanid
276 retval
+= " --bondslaves %s" % self
.bondslaves
278 retval
+= " --bondopts %s" % self
.bondopts
283 class RHEL7_NetworkData(F20_NetworkData
):
284 removedKeywords
= F20_NetworkData
.removedKeywords
285 removedAttrs
= F20_NetworkData
.removedAttrs
287 def __init__(self
, *args
, **kwargs
):
288 F20_NetworkData
.__init
__(self
, *args
, **kwargs
)
289 self
.interfacename
= kwargs
.get("interfacename", "")
291 def _getArgsAsStr(self
):
292 retval
= F20_NetworkData
._getArgsAsStr
(self
)
293 if self
.interfacename
:
294 retval
+= " --interfacename=%s" % self
.interfacename
298 class FC3_Network(KickstartCommand
):
299 removedKeywords
= KickstartCommand
.removedKeywords
300 removedAttrs
= KickstartCommand
.removedAttrs
302 def __init__(self
, writePriority
=0, *args
, **kwargs
):
303 KickstartCommand
.__init
__(self
, writePriority
, *args
, **kwargs
)
304 self
.bootprotoList
= [BOOTPROTO_DHCP
, BOOTPROTO_BOOTP
,
307 self
.op
= self
._getParser
()
309 self
.network
= kwargs
.get("network", [])
314 for nic
in self
.network
:
315 retval
+= nic
.__str
__()
318 return "# Network information\n" + retval
322 def _getParser(self
):
323 op
= KSOptionParser()
324 op
.add_option("--bootproto", dest
="bootProto",
325 default
=BOOTPROTO_DHCP
,
326 choices
=self
.bootprotoList
)
327 op
.add_option("--dhcpclass", dest
="dhcpclass")
328 op
.add_option("--device", dest
="device")
329 op
.add_option("--essid", dest
="essid")
330 op
.add_option("--ethtool", dest
="ethtool")
331 op
.add_option("--gateway", dest
="gateway")
332 op
.add_option("--hostname", dest
="hostname")
333 op
.add_option("--ip", dest
="ip")
334 op
.add_option("--mtu", dest
="mtu")
335 op
.add_option("--nameserver", dest
="nameserver")
336 op
.add_option("--netmask", dest
="netmask")
337 op
.add_option("--nodns", dest
="nodns", action
="store_true",
339 op
.add_option("--onboot", dest
="onboot", action
="store",
341 op
.add_option("--wepkey", dest
="wepkey")
344 def parse(self
, args
):
345 (opts
, _extra
) = self
.op
.parse_args(args
=args
, lineno
=self
.lineno
)
346 nd
= self
.handler
.NetworkData()
347 self
._setToObj
(self
.op
, opts
, nd
)
348 nd
.lineno
= self
.lineno
350 # Check for duplicates in the data list.
351 if nd
in self
.dataList():
352 warnings
.warn(_("A network device with the name %s has already been defined.") % nd
.device
)
359 class FC4_Network(FC3_Network
):
360 removedKeywords
= FC3_Network
.removedKeywords
361 removedAttrs
= FC3_Network
.removedAttrs
363 def _getParser(self
):
364 op
= FC3_Network
._getParser
(self
)
365 op
.add_option("--notksdevice", dest
="notksdevice", action
="store_true",
369 class FC6_Network(FC4_Network
):
370 removedKeywords
= FC4_Network
.removedKeywords
371 removedAttrs
= FC4_Network
.removedAttrs
373 def _getParser(self
):
374 op
= FC4_Network
._getParser
(self
)
375 op
.add_option("--noipv4", dest
="noipv4", action
="store_true",
377 op
.add_option("--noipv6", dest
="noipv6", action
="store_true",
381 class F8_Network(FC6_Network
):
382 removedKeywords
= FC6_Network
.removedKeywords
383 removedAttrs
= FC6_Network
.removedAttrs
385 def _getParser(self
):
386 op
= FC6_Network
._getParser
(self
)
387 op
.add_option("--ipv6", dest
="ipv6")
390 class F9_Network(F8_Network
):
391 removedKeywords
= F8_Network
.removedKeywords
392 removedAttrs
= F8_Network
.removedAttrs
394 def __init__(self
, writePriority
=0, *args
, **kwargs
):
395 F8_Network
.__init
__(self
, writePriority
, *args
, **kwargs
)
396 self
.bootprotoList
.append(BOOTPROTO_QUERY
)
398 def _getParser(self
):
399 op
= F8_Network
._getParser
(self
)
400 op
.add_option("--bootproto", dest
="bootProto",
401 default
=BOOTPROTO_DHCP
,
402 choices
=self
.bootprotoList
)
405 class F16_Network(F9_Network
):
406 removedKeywords
= F9_Network
.removedKeywords
407 removedAttrs
= F9_Network
.removedAttrs
409 def __init__(self
, writePriority
=0, *args
, **kwargs
):
410 F9_Network
.__init
__(self
, writePriority
, *args
, **kwargs
)
411 self
.bootprotoList
.append(BOOTPROTO_IBFT
)
413 def _getParser(self
):
414 op
= F9_Network
._getParser
(self
)
415 op
.add_option("--activate", dest
="activate", action
="store_true",
417 op
.add_option("--nodefroute", dest
="nodefroute", action
="store_true",
419 op
.add_option("--wpakey", dest
="wpakey", action
="store", default
="")
422 class F18_Network(F16_Network
):
426 for nd
in self
.dataList():
431 class F19_Network(F18_Network
):
433 def _getParser(self
):
434 op
= F18_Network
._getParser
(self
)
435 op
.add_option("--bondslaves", dest
="bondslaves", action
="store",
437 op
.add_option("--bondopts", dest
="bondopts", action
="store",
439 op
.add_option("--vlanid", dest
="vlanid")
440 op
.add_option("--ipv6gateway", dest
="ipv6gateway", action
="store",
444 class F20_Network(F19_Network
):
446 def _getParser(self
):
447 # see the tests for teamslaves option
448 def teamslaves_cb(option
, opt_str
, value
, parser
):
449 # value is of: "<DEV1>['<JSON_CONFIG1>'],<DEV2>['<JSON_CONFIG2>'],..."
450 # for example: "eth1,eth2'{"prio": 100}',eth3"
453 # Although slaves, having optional config, are separated by ","
454 # first extract json configs because they can contain the ","
455 parts
= value
.split("'")
456 # parts == ['eth1,eth2', '{"prio": 100}', ',eth3']
457 # ensure the list has even number of items for further zipping,
458 # for odd number of items
459 if len(parts
) % 2 == 1:
460 # if the list ends with an empty string which must be a leftover
461 # from splitting string not ending with device eg
462 # "eth1,eth2'{"prio":100"}'"
466 # if not (our example), add empty config for the last device
469 # parts == ['eth1,eth2', '{"prio": 100}', ',eth3', '']
470 # zip devices with their configs
472 for devs
, cfg
in zip(it
,it
):
474 # devs == "eth1,eth2", cfg == '{"prio": 100}'
475 devs
= devs
.strip(',').split(',')
476 # devs == ["eth1", "eth2"]
477 # initialize config of all devs but the last one to empty
479 teamslaves
.append((d
, ''))
480 # teamslaves == [("eth1", '')]
481 # and set config of the last device
482 teamslaves
.append((devs
[-1], cfg
))
483 # teamslaves == [('eth1', ''), ('eth2', '{"prio": 100}']
484 parser
.values
.teamslaves
= teamslaves
486 op
= F19_Network
._getParser
(self
)
487 op
.add_option("--teamslaves", dest
="teamslaves", action
="callback",
488 callback
=teamslaves_cb
, nargs
=1, type="string")
489 op
.add_option("--teamconfig", dest
="teamconfig", action
="store",
493 class F21_Network(F20_Network
):
494 def _getParser(self
):
495 op
= F20_Network
._getParser
(self
)
496 op
.add_option("--interfacename", dest
="interfacename", action
="store",
500 class RHEL4_Network(FC3_Network
):
501 removedKeywords
= FC3_Network
.removedKeywords
502 removedAttrs
= FC3_Network
.removedAttrs
504 def _getParser(self
):
505 op
= FC3_Network
._getParser
(self
)
506 op
.add_option("--notksdevice", dest
="notksdevice", action
="store_true",
510 class RHEL5_Network(FC6_Network
):
511 removedKeywords
= FC6_Network
.removedKeywords
512 removedAttrs
= FC6_Network
.removedAttrs
514 def __init__(self
, writePriority
=0, *args
, **kwargs
):
515 FC6_Network
.__init
__(self
, writePriority
, *args
, **kwargs
)
516 self
.bootprotoList
.append(BOOTPROTO_QUERY
)
518 def _getParser(self
):
519 op
= FC6_Network
._getParser
(self
)
520 op
.add_option("--bootproto", dest
="bootProto",
521 default
=BOOTPROTO_DHCP
,
522 choices
=self
.bootprotoList
)
525 class RHEL6_Network(F9_Network
):
526 removedKeywords
= F9_Network
.removedKeywords
527 removedAttrs
= F9_Network
.removedAttrs
529 def __init__(self
, writePriority
=0, *args
, **kwargs
):
530 F9_Network
.__init
__(self
, writePriority
, *args
, **kwargs
)
531 self
.bootprotoList
.append(BOOTPROTO_IBFT
)
533 def _getParser(self
):
534 op
= F9_Network
._getParser
(self
)
535 op
.add_option("--activate", dest
="activate", action
="store_true",
537 op
.add_option("--nodefroute", dest
="nodefroute", action
="store_true",
539 op
.add_option("--vlanid", dest
="vlanid")
540 op
.add_option("--bondslaves", dest
="bondslaves")
541 op
.add_option("--bondopts", dest
="bondopts")
544 def validate_network_interface_name(name
):
545 """Check if the given network interface name is valid, return an error message
546 if an error is found or None if no errors are found
548 :param str name: name to validate
549 :returns: error message or None if no error is found
550 :rtype: str or NoneType
552 # (for reference see the NetworkManager source code:
553 # NetworkManager/src/settings/plugins/ifcfg-rh/reader.c
554 # and the make_vlan_setting function)
558 # if it contains '.', vlan id should follow (eg 'ens7.171', 'mydev.171')
559 (vlan
, dot
, id_candidate
) = name
.partition(".")
561 # 'vlan' can't be followed by a '.'
563 return _("When using the <prefix>.<vlan id> interface name notation, <prefix> can't be equal to 'vlan'.")
565 vlan_id
= int(id_candidate
)
567 return _("If network --interfacename contains a '.', valid vlan id should follow.")
569 # if it starts with 'vlan', vlan id should follow ('vlan171')
570 (empty
, sep
, id_candidate
) = name
.partition("vlan")
571 if sep
and empty
== "":
572 # if we checked only for empty == "", we would evaluate missing interface name as an error
574 vlan_id
= int(id_candidate
)
576 return _("If network --interfacename starts with 'vlan', valid vlan id should follow.")
578 # check if the vlan id is in range
579 if vlan_id
is not None:
580 if not(MIN_VLAN_ID
<= vlan_id
<= MAX_VLAN_ID
):
581 return _("The vlan id out of the %d-%d vlan id range.") % (MIN_VLAN_ID
, MAX_VLAN_ID
)
583 # network interface name seems to be valid (no error found)
586 class RHEL7_Network(F20_Network
):
587 def _getParser(self
):
588 op
= F20_Network
._getParser
(self
)
589 op
.add_option("--interfacename", dest
="interfacename", action
="store",
593 def parse(self
, args
):
594 # call the overridden command to do it's job first
595 retval
= F20_Network
.parse(self
, args
)
597 # validate the network interface name
598 error_message
= validate_network_interface_name(retval
.interfacename
)
599 # something is wrong with the interface name
600 if error_message
is not None:
601 raise KickstartValueError(formatErrorMsg(self
.lineno
,msg
=error_message
))