Edward Haas has uploaded a new change for review.

Change subject: net: Adding bond api with sysfs driver under link
......................................................................

net: Adding bond api with sysfs driver under link

Change-Id: I75f4f6b370f29411158e288610a1677b52998546
Signed-off-by: Edward Haas <edwa...@redhat.com>
---
A lib/vdsm/network/link/bond.py
A tests/network/link_bond_test.py
2 files changed, 236 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/28/62828/1

diff --git a/lib/vdsm/network/link/bond.py b/lib/vdsm/network/link/bond.py
new file mode 100644
index 0000000..11498f8
--- /dev/null
+++ b/lib/vdsm/network/link/bond.py
@@ -0,0 +1,160 @@
+# Copyright 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+from __future__ import absolute_import
+
+import abc
+import os
+import six
+
+from . import iface
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BondAPI(object):
+    """
+    Bond driver interface.
+    """
+    def __init__(self, name, slaves=(), options=None):
+        self._master = name
+        self._slaves = set(slaves)
+        self._options = options
+        if self.is_bond():
+            self._import_existing()
+
+    @abc.abstractmethod
+    def create(self):
+        pass
+
+    @abc.abstractmethod
+    def destroy(self):
+        pass
+
+    @abc.abstractmethod
+    def add_slaves(self, slaves):
+        pass
+
+    @abc.abstractmethod
+    def del_slaves(self, slaves):
+        pass
+
+    @abc.abstractmethod
+    def set_options(self, options):
+        pass
+
+    @abc.abstractmethod
+    def is_bond(self):
+        pass
+
+    @abc.abstractmethod
+    def active_slave(self):
+        pass
+
+    @property
+    def master(self):
+        return self._master
+
+    @property
+    def slaves(self):
+        return self._slaves
+
+    @property
+    def options(self):
+        return self._options
+
+    def up(self):
+        self._setlinks(up=True)
+
+    def down(self):
+        self._setlinks(up=False)
+
+    @abc.abstractmethod
+    def _import_existing(self):
+        pass
+
+    def _setlinks(self, up):
+        setstate = iface.up if up else iface.down
+        setstate(self._master)
+        for slave in self._slaves:
+            setstate(slave)
+
+
+class BondSysFS(BondAPI):
+
+    BONDING_MASTERS = '/sys/class/net/bonding_masters'
+    BONDING_PATH = '/sys/class/net/%s/bonding'
+    BONDING_SLAVES = BONDING_PATH + '/slaves'
+    BONDING_ACTIVE_SLAVE = BONDING_PATH + '/active_slave'
+    BONDING_OPT = BONDING_PATH + '/%s'
+
+    def __init__(self, name, slaves=(), options=None):
+        super(BondSysFS, self).__init__(name, slaves, options)
+
+    def create(self):
+        with open(self.BONDING_MASTERS, 'w') as f:
+            f.write('+%s' % self._master)
+        if self._slaves:
+            self.add_slaves(self._slaves)
+
+    def destroy(self):
+        with open(self.BONDING_MASTERS, 'w') as f:
+            f.write('-%s' % self._master)
+
+    def add_slaves(self, slaves):
+        self._slaves |= set(slaves)
+        for slave in slaves:
+            iface.down(slave)
+            with open(self.BONDING_SLAVES % self._master, 'w') as f:
+                f.write('+%s' % slave)
+
+    def del_slaves(self, slaves):
+        self._slaves -= set(slaves)
+        for slave in slaves:
+            iface.down(slave)
+            with open(self.BONDING_SLAVES % self._master, 'w') as f:
+                f.write('-%s' % slave)
+
+    def set_options(self, options):
+        self._options.update(options)
+        for key, value in options:
+            with open(self.BONDING_OPT % (self._master, key), 'w') as f:
+                f.write(value)
+
+    def is_bond(self):
+        return os.path.exists(self.BONDING_PATH % self._master)
+
+    def active_slave(self):
+        with open(self.BONDING_ACTIVE_SLAVE % self._master) as f:
+            return f.readline().rstrip()
+
+    def _import_existing(self):
+        with open(self.BONDING_SLAVES % self._master) as f:
+            self._slaves = set(f.readline().split())
+        # TODO: Support options
+        self._options = None
+
+
+# TODO: Use a configuration parameter to determine which driver to use.
+def _bond_driver():
+    """
+    Return the bond driver implementation.
+    """
+    return BondSysFS
+
+
+Bond = _bond_driver()
diff --git a/tests/network/link_bond_test.py b/tests/network/link_bond_test.py
new file mode 100644
index 0000000..0e815d0
--- /dev/null
+++ b/tests/network/link_bond_test.py
@@ -0,0 +1,76 @@
+# Copyright 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty 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
+#
+# Refer to the README and COPYING files for full details of the license
+#
+from __future__ import absolute_import
+
+from contextlib import contextmanager
+
+from nose.plugins.attrib import attr
+
+from testlib import VdsmTestCase as TestCaseBase
+
+from .nettestlib import dummy_devices
+
+from vdsm.network.link import iface
+from vdsm.network.link.bond import Bond
+from vdsm.utils import random_iface_name
+
+
+@attr(type='integration')
+class LinkBondTests(TestCaseBase):
+
+    def test_bond_without_slaves(self):
+        with bond_device() as bond:
+            self.assertFalse(iface.is_up(bond.master))
+
+    def test_bond_with_slaves(self):
+        with dummy_devices(2) as (nic1, nic2):
+            with bond_device() as bond:
+                bond.add_slaves((nic1, nic2))
+                self.assertFalse(iface.is_up(bond.master))
+
+    def test_bond_devices_are_up(self):
+        with dummy_devices(2) as (nic1, nic2):
+            with bond_device() as bond:
+                bond.add_slaves((nic1, nic2))
+                bond.up()
+                self.assertTrue(iface.is_up(nic1))
+                self.assertTrue(iface.is_up(nic2))
+                self.assertTrue(iface.is_up(bond.master))
+
+    def test_bond_exists(self):
+        with dummy_devices(2) as (nic1, nic2):
+            with bond_device() as _bond:
+                _bond.add_slaves((nic1, nic2))
+                _bond.up()
+
+                bond = Bond(_bond.master)
+                self.assertEqual(bond.slaves, set((nic1, nic2)))
+                # TODO: Support options
+                self.assertEqual(bond.options, None)
+
+
+@contextmanager
+def bond_device(prefix='bond_', max_length=11):
+    bond_name = random_iface_name(prefix, max_length)
+    bond = Bond(bond_name)
+    bond.create()
+    try:
+        yield bond
+    finally:
+        bond.destroy()


-- 
To view, visit https://gerrit.ovirt.org/62828
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I75f4f6b370f29411158e288610a1677b52998546
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Edward Haas <edwa...@redhat.com>
_______________________________________________
vdsm-patches mailing list
vdsm-patches@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/vdsm-patches@lists.fedorahosted.org

Reply via email to