[PATCH] (v2) Add support for network team devices (#1003591)
Radek Vykydal
rvykydal at redhat.com
Tue Nov 12 13:33:27 UTC 2013
---
pykickstart/commands/network.py | 74 +++++++++++++++++++++++++++++++++++++++++
pykickstart/handlers/control.py | 8 ++---
tests/commands/network.py | 73 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 151 insertions(+), 4 deletions(-)
create mode 100644 tests/commands/network.py
diff --git a/pykickstart/commands/network.py b/pykickstart/commands/network.py
index 6f50ac1..1412dc7 100644
--- a/pykickstart/commands/network.py
+++ b/pykickstart/commands/network.py
@@ -193,6 +193,31 @@ class F19_NetworkData(F16_NetworkData):
return retval
+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
+
class RHEL4_NetworkData(FC3_NetworkData):
removedKeywords = FC3_NetworkData.removedKeywords
removedAttrs = FC3_NetworkData.removedAttrs
@@ -384,6 +409,55 @@ class F19_Network(F18_Network):
default="")
return op
+class F20_Network(F19_Network):
+
+ def _getParser(self):
+ # see the tests for teamslaves option
+ def teamslaves_cb(option, opt_str, value, parser):
+ # 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 its 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}']
+ parser.values.teamslaves = teamslaves
+
+ op = F19_Network._getParser(self)
+ op.add_option("--teamslaves", dest="teamslaves", action="callback",
+ callback=teamslaves_cb, nargs=1, type="string")
+ op.add_option("--teamconfig", dest="teamconfig", action="store",
+ default="")
+ return op
+
class RHEL4_Network(FC3_Network):
removedKeywords = FC3_Network.removedKeywords
removedAttrs = FC3_Network.removedAttrs
diff --git a/pykickstart/handlers/control.py b/pykickstart/handlers/control.py
index 0139f9a..2566c89 100644
--- a/pykickstart/handlers/control.py
+++ b/pykickstart/handlers/control.py
@@ -1058,7 +1058,7 @@ commandMap = {
"mediacheck": mediacheck.FC4_MediaCheck,
"method": method.F19_Method,
"multipath": multipath.FC6_MultiPath,
- "network": network.F19_Network,
+ "network": network.F20_Network,
"nfs": nfs.FC6_NFS,
"part": partition.F20_Partition,
"partition": partition.F20_Partition,
@@ -1347,7 +1347,7 @@ commandMap = {
"mediacheck": mediacheck.FC4_MediaCheck,
"method": method.F19_Method,
"multipath": multipath.FC6_MultiPath,
- "network": network.F19_Network,
+ "network": network.F20_Network,
"nfs": nfs.FC6_NFS,
"part": partition.F18_Partition,
"partition": partition.F18_Partition,
@@ -1655,7 +1655,7 @@ dataMap = {
"IscsiData": iscsi.F17_IscsiData,
"LogVolData": logvol.F20_LogVolData,
"MultiPathData": multipath.FC6_MultiPathData,
- "NetworkData": network.F19_NetworkData,
+ "NetworkData": network.F20_NetworkData,
"PartData": partition.F18_PartData,
"RaidData": raid.F18_RaidData,
"RepoData": repo.F15_RepoData,
@@ -1724,7 +1724,7 @@ dataMap = {
"IscsiData": iscsi.F17_IscsiData,
"LogVolData": logvol.F18_LogVolData,
"MultiPathData": multipath.FC6_MultiPathData,
- "NetworkData": network.F19_NetworkData,
+ "NetworkData": network.F20_NetworkData,
"PartData": partition.F18_PartData,
"RaidData": raid.F18_RaidData,
"RepoData": repo.F15_RepoData,
diff --git a/tests/commands/network.py b/tests/commands/network.py
new file mode 100644
index 0000000..9643c74
--- /dev/null
+++ b/tests/commands/network.py
@@ -0,0 +1,73 @@
+#
+# Radek Vykydal <rvykydal at redhat.com>
+#
+# Copyright 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. 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.
+#
+import unittest
+from tests.baseclass import *
+
+from pykickstart.errors import *
+from pykickstart.commands.network import *
+
+class F20_TestCase(CommandTest):
+ command = "network"
+
+ def runTest(self):
+
+ # team device
+
+ cmd = "network --device team0 --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\\\"}}\" --activate"
+ self.assert_parse(cmd)
+
+ cmd = "network --device team0 --bootproto dhcp --teamslaves=p3p1,p3p2 --teamconfig=\"{\\\"runner\\\": {\\\"name\\\": \\\"roundrobin\\\"}}\" --activate"
+ self.assert_parse(cmd)
+
+ # --teamslaves
+ # --teamslaves="<DEV1>['<CONFIG1>'],<DEV2>['<CONFIG2>'],..."
+ # CONFIGX is json with " escaped to \"
+
+ teamslaves_strings = [
+ r"eth1,eth2",
+ r"eth1,eth2'{\"prio\": 100}'",
+ r"eth1'{\"prio\": -10, \"sticky\": true}',eth2",
+ r"eth1'{\"prio\": -10, \"sticky\": true}',eth2'{\"prio\": 100}'",
+ r"eth1,eth2,eth3",
+ r"eth1,eth2'{\"prio\": 100}',eth3",
+ ]
+
+ teamslaves_values = [
+ [('eth1',""), ('eth2',"")],
+ [('eth1',""), ('eth2','{"prio": 100}')],
+ [('eth1','{"prio": -10, "sticky": true}'), ('eth2',"")],
+ [('eth1','{"prio": -10, "sticky": true}'), ('eth2','{"prio": 100}')],
+ [('eth1',""), ('eth2',""), ('eth3',"")],
+ [('eth1',""), ('eth2','{"prio": 100}'), ('eth3',"")],
+ ]
+
+ for string, value in zip(teamslaves_strings, teamslaves_values):
+ network_data = self.assert_parse("network --device team0 --bootproto=dhcp --teamslaves=\"%s\"" % string)
+ self.assertEquals(network_data.teamslaves, value)
+
+ for value in teamslaves_values:
+ nd = self.assert_parse("network --device team0 --bootproto=dhcp")
+ nd.teamslaves = value
+ s = "%s" % nd
+ nd2 = self.assert_parse(s)
+ self.assertEquals(value, nd2.teamslaves)
+
+if __name__ == "__main__":
+ unittest.main()
--
1.7.11.7
More information about the anaconda-patches
mailing list