Change in vdsm[master]: netinfo, tool: Add a vdsm-tool to determine bonding defaults...

osvoboda at redhat.com osvoboda at redhat.com
Fri Sep 26 13:19:48 UTC 2014


Ondřej Svoboda has uploaded a new change for review.

Change subject: netinfo, tool: Add a vdsm-tool to determine bonding defaults offline
......................................................................

netinfo, tool: Add a vdsm-tool to determine bonding defaults offline

Change-Id: I89b907ba80f23f417d5e481db9350247445ab772
Signed-off-by: Ondřej Svoboda <osvoboda at redhat.com>
---
M init/vdsmd_init_common.sh.in
M lib/vdsm/netinfo.py
A lib/vdsm/tool/dump_bonding_defaults.py
M tests/netinfoTests.py
M vdsm/sudoers.vdsm.in
5 files changed, 163 insertions(+), 113 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/03/33403/1

diff --git a/init/vdsmd_init_common.sh.in b/init/vdsmd_init_common.sh.in
index 298b658..0b72b69 100644
--- a/init/vdsmd_init_common.sh.in
+++ b/init/vdsmd_init_common.sh.in
@@ -100,6 +100,11 @@
 }
 
 
+task_dump_bonding_defaults(){
+    "${VDSM_TOOL}" dump_bonding_defaults > "@VDSMLIBDIR@/bonding-defaults.json"
+}
+
+
 task_tune_system(){
     "@SYSCTL_PATH@" -q -p "/etc/sysctl.d/vdsm.conf"
 }
@@ -240,6 +245,7 @@
             nwfilter \
             dummybr \
             load_needed_modules \
+            dump_bonding_defaults \
             tune_system \
             test_space \
             test_lo \
diff --git a/lib/vdsm/netinfo.py b/lib/vdsm/netinfo.py
index fcca5a7..cd47062 100644
--- a/lib/vdsm/netinfo.py
+++ b/lib/vdsm/netinfo.py
@@ -19,7 +19,6 @@
 #
 
 from collections import defaultdict
-from contextlib import contextmanager
 import errno
 from glob import iglob
 from datetime import datetime
@@ -27,10 +26,8 @@
 from itertools import chain
 import logging
 import os
-import random
 import shlex
 import socket
-import string
 import struct
 from xml.dom import minidom
 
@@ -45,10 +42,11 @@
 from .ipwrapper import routeShowGateways
 from . import libvirtconnection
 from .netconfpersistence import RunningConfig
-from .utils import execCmd, memoized, pgrep, CommandPath
+from .utils import memoized
 from .netlink import link as nl_link
 from .netlink import addr as nl_addr
 from .netlink import route as nl_route
+from .tool.dump_bonding_defaults import BONDING_DEFAULTS
 
 
 NET_CONF_DIR = '/etc/sysconfig/network-scripts/'
@@ -77,8 +75,6 @@
 ))
 _IFCFG_ZERO_SUFFIXED = frozenset(
     ('IPADDR0', 'GATEWAY0', 'PREFIX0', 'NETMASK0'))
-_TEE_BINARY = CommandPath('tee', constants.EXT_TEE)
-_NM_CLI_BINARY = CommandPath('nmcli', constants.EXT_NMCLI)
 
 LIBVIRT_NET_PREFIX = 'vdsm-'
 DEFAULT_MTU = '1500'
@@ -148,7 +144,7 @@
     return opts
 
 
-def _realBondOpts(bond):
+def realBondOpts(bond):
     """
     Return a dictionary in the same format as bondOpts(). Exclude entries that
     are not bonding options, e.g. 'ad_num_ports' or 'slaves'.
@@ -405,82 +401,13 @@
     return paddr
 
 
-def _randomIfaceName():
-    MAX_LENGTH = 15
-    CHARS = string.ascii_lowercase + string.ascii_uppercase + string.digits
-
-    return ''.join(random.choice(CHARS) for _ in range(MAX_LENGTH))
-
-
- at contextmanager
-def _avoidNetworkManager(interface):
-    """Make a network interface unmanaged by NetworkManager.
-
-    Until NM supports placing its 'unmanaged-devices' directive in
-    /etc/NetworkManager/conf.d/00-server.conf we are left with a hack.
-    The directive should also support globbing so we do not have to use
-    a predictable name for e.g. the reference bond (but we could accept that,
-    too).
-
-    Please see https://bugzilla.redhat.com/show_bug.cgi?id=1136843"""
-    has_nm = pgrep('NetworkManager')
-
-    if has_nm:
-        nmcli = _NM_CLI_BINARY.cmd
-        ifcfgPath = NET_CONF_PREF + interface
-        execCmd([_TEE_BINARY.cmd, ifcfgPath], sudo=True,
-                data='DEVICE=%s\nNM_CONTROLLED=no\n' % interface)
-
-        rc, _, _ = execCmd([nmcli, 'conn', 'load', ifcfgPath], sudo=True)
-        if rc:
-            raise RuntimeError('Failed to unmanage %s.' % interface)
-    try:
-        yield
-    finally:
-        if has_nm:
-            execCmd([nmcli, 'conn', 'delete', interface], sudo=True)
-            execCmd([constants.EXT_RM, ifcfgPath], sudo=True)
-
-
 @memoized
 def _getAllDefaultBondingOptions():
     """
     Return default options per mode, in a dictionary of dictionaries. All keys
-    are strings.
+    are numeric modes stored as strings for coherence with 'mode' option value.
     """
-    teeCmd = _TEE_BINARY.cmd
-    MAX_MODE = 6
-
-    bondName = _randomIfaceName()
-    with _avoidNetworkManager(bondName):
-        rc, _, err = execCmd([teeCmd, BONDING_MASTERS], data='+' + bondName,
-                             sudo=True)
-        if rc:
-            raise RuntimeError('Creating a reference bond failed',
-                               '\n'.join(err))
-        opts = {}
-        try:
-            defaultMode = bondOpts(bondName, keys=['mode'])['mode']
-
-            # read default values for all modes
-            for mode in range(0, MAX_MODE + 1):
-                mode = str(mode)
-                sysfsMode = BONDING_OPT % (bondName, 'mode')
-                rc, _, err = execCmd([teeCmd, sysfsMode], data=mode, sudo=True)
-                if rc:
-                    raise RuntimeError('Changing the mode of the reference '
-                                       'bond failed. Is NetworkManager '
-                                       'running?', '\n'.join(err))
-
-                # only read non-empty options
-                opts[mode] = dict(((opt, val) for (opt, val) in
-                                   _realBondOpts(bondName).iteritems() if val))
-                opts[mode]['mode'] = defaultMode
-
-        finally:
-            execCmd([teeCmd, BONDING_MASTERS], data='-' + bondName, sudo=True)
-
-    return opts
+    return json.load(open(constants.P_VDSM_BONDING_DEFAULTS).read())
 
 
 @memoized
diff --git a/lib/vdsm/tool/dump_bonding_defaults.py b/lib/vdsm/tool/dump_bonding_defaults.py
new file mode 100644
index 0000000..27311c3
--- /dev/null
+++ b/lib/vdsm/tool/dump_bonding_defaults.py
@@ -0,0 +1,121 @@
+#! /usr/bin/python
+# Copyright 2014 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
+#
+
+
+import json
+import os
+import random
+import string
+
+from ..constants import EXT_NMCLI, EXT_RM, P_VDSM_LIB
+from ..netinfo import (BONDING_MASTERS, BONDING_OPT, NET_CONF_PREF, bondOpts,
+                       realBondOpts)
+from ..utils import execCmd, pgrep
+from . import expose, ExtraArgsError
+
+
+BONDING_DEFAULTS = os.path.join(P_VDSM_LIB, 'bonding-defaults.json')
+
+
+def _randomIfaceName():
+    MAX_LENGTH = 15
+    CHARS = string.ascii_lowercase + string.ascii_uppercase + string.digits
+
+    return ''.join(random.choice(CHARS) for _ in range(MAX_LENGTH))
+
+
+ at contextmanager
+def _avoidNetworkManager(interface):
+    """Make a network interface unmanaged by NetworkManager.
+
+    Until NM supports placing its 'unmanaged-devices' directive in
+    /etc/NetworkManager/conf.d/00-server.conf we are left with a hack.
+    The directive should also support globbing so we do not have to use
+    a predictable name for e.g. the reference bond (but we could accept that,
+    too).
+
+    Please see https://bugzilla.redhat.com/show_bug.cgi?id=1136843"""
+    has_nm = pgrep('NetworkManager')
+
+    if has_nm:
+        ifcfgPath = NET_CONF_PREF + interface
+        with open(ifcfgPath, 'w') as ifcfgFile:
+            ifcfgFile.write('DEVICE=%s\nNM_CONTROLLED=no\n' % interface)
+
+        execCmd([EXT_NMCLI, 'conn', 'load', ifcfgPath])
+    try:
+        yield
+    finally:
+        if has_nm:
+            execCmd([EXT_NMCLI, 'conn', 'delete', interface])
+            execCmd([EXT_RM, ifcfgPath])
+
+
+def _getAllDefaultBondingOptions():
+    """
+    Return default options per mode, in a dictionary of dictionaries. All keys
+    are strings.
+    """
+    MAX_MODE = 6
+    # TODO: We can just use something like REFERENCE_BOND = ';vdsmrefbond;'
+    bondName = _randomIfaceName()
+    opts = {}
+
+    with _avoidNetworkManager(bondName):
+        with open(BONDING_MASTERS, 'w') as bonds:
+            bonds.write('+' + bondName)
+
+        try:
+            defaultMode = bondOpts(bondName, keys=['mode'])['mode']
+
+            # read default values for all modes
+            for mode in range(0, MAX_MODE + 1):
+                mode = str(mode)
+                with open(BONDING_OPT % (bondName, 'mode'), 'w') as opt:
+                    opt.write(mode)
+
+                # only read non-empty options
+                opts[mode] = dict(((opt, val) for (opt, val) in
+                                   realBondOpts(bondName).iteritems() if val))
+                opts[mode]['mode'] = defaultMode
+
+        finally:
+            with open(BONDING_MASTERS, 'w') as bonds:
+                bonds.write('-' + bondName)
+
+    return opts
+
+
+ at expose('dump_bonding_defaults')
+def main(*args):
+    """dump_bonding_defaults
+
+    Read bonding option defaults and print them out as a dictionary (per mode)
+    in JSON format.
+    """
+
+    if len(args) > 1:
+        raise ExtraArgsError()
+
+    with open(BONDING_DEFAULTS, 'w') as defaults:
+        defaults.write(json.dumps(_getAllDefaultBondingOptions()))
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/netinfoTests.py b/tests/netinfoTests.py
index 5828399..63c11ae 100644
--- a/tests/netinfoTests.py
+++ b/tests/netinfoTests.py
@@ -26,16 +26,17 @@
 from vdsm import ipwrapper
 from vdsm import netconfpersistence
 from vdsm import netinfo
-from vdsm.netinfo import (getBootProtocol, getDhclientIfaces, BONDING_MASTERS,
-                          BONDING_OPT, _randomIfaceName, _getBondingOptions,
-                          _avoidNetworkManager)
+from vdsm.netinfo import getBootProtocol, getDhclientIfaces
+# BONDING_MASTERS, BONDING_OPT, _randomIfaceName, _getBondingOptions
+# _avoidNetworkManager
 from vdsm.netlink import addr as nl_addr
 
 from functional import dummy, veth
 from ipwrapperTests import _fakeTypeDetection
 from monkeypatch import MonkeyPatch, MonkeyPatchScope
 from testlib import VdsmTestCase as TestCaseBase, namedTemporaryDir
-from testValidation import ValidateRunningAsRoot, RequireBondingMod
+from testValidation import ValidateRunningAsRoot
+# RequireBondingMod
 
 # speeds defined in ethtool
 ETHTOOL_SPEEDS = set([10, 100, 1000, 2500, 10000])
@@ -301,27 +302,28 @@
         self.assertNotIn('expired', dhcp4)
         self.assertNotIn('expired2', dhcp4)
 
-    @ValidateRunningAsRoot
-    @RequireBondingMod
-    def testGetBondingOptions(self):
-        INTERVAL = '12345'
-        bondName = _randomIfaceName()
-
-        with _avoidNetworkManager(bondName):
-            with open(BONDING_MASTERS, 'w') as bonds:
-                bonds.write('+' + bondName)
-                bonds.flush()
-
-                try:
-                    with self.assertNotRaises():
-                        self.assertEqual(_getBondingOptions(bondName), {})
-
-                        with open(BONDING_OPT % (bondName, 'miimon'),
-                                  'w') as opt:
-                            opt.write(INTERVAL)
-
-                    self.assertEqual(_getBondingOptions(bondName),
-                                     {'miimon': INTERVAL})
-
-                finally:
-                    bonds.write('-' + bondName)
+# TODO: move to toolTests.py?
+#    @ValidateRunningAsRoot
+#    @RequireBondingMod
+#    def testGetBondingOptions(self):
+#        INTERVAL = '12345'
+#        bondName = _randomIfaceName()
+#
+#        with _avoidNetworkManager(bondName):
+#            with open(BONDING_MASTERS, 'w') as bonds:
+#                bonds.write('+' + bondName)
+#                bonds.flush()
+#
+#                try:
+#                    with self.assertNotRaises():
+#                        self.assertEqual(_getBondingOptions(bondName), {})
+#
+#                        with open(BONDING_OPT % (bondName, 'miimon'),
+#                                  'w') as opt:
+#                            opt.write(INTERVAL)
+#
+#                    self.assertEqual(_getBondingOptions(bondName),
+#                                     {'miimon': INTERVAL})
+#
+#                finally:
+#                    bonds.write('-' + bondName)
diff --git a/vdsm/sudoers.vdsm.in b/vdsm/sudoers.vdsm.in
index 465b530..2b745d3 100644
--- a/vdsm/sudoers.vdsm.in
+++ b/vdsm/sudoers.vdsm.in
@@ -30,13 +30,7 @@
     @SETSID_PATH@ @IONICE_PATH@ -c ? -n ? @SU_PATH@ vdsm -s /bin/sh -c /usr/libexec/vdsm/spmprotect.sh*, \
     @SERVICE_PATH@ vdsmd *, \
     @REBOOT_PATH@ -f
-Cmnd_Alias VDSM_NETWORK = \
-    @NMCLI_PATH@, \
-    @TEE_PATH@ /etc/sysconfig/network-scripts/ifcfg-*, \
-    @RM_PATH@ /etc/sysconfig/network-scripts/ifcfg-*, \
-    @TEE_PATH@ /sys/class/net/bonding_masters, \
-    @TEE_PATH@ /sys/class/net/*/bonding/mode
 
-vdsm  ALL=(ALL) NOPASSWD: VDSM_LIFECYCLE, VDSM_STORAGE, VDSM_NETWORK
+vdsm  ALL=(ALL) NOPASSWD: VDSM_LIFECYCLE, VDSM_STORAGE
 Defaults:vdsm !requiretty
 Defaults:vdsm !syslog


-- 
To view, visit http://gerrit.ovirt.org/33403
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I89b907ba80f23f417d5e481db9350247445ab772
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Ondřej Svoboda <osvoboda at redhat.com>


More information about the vdsm-patches mailing list