Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

491 lines (366 sloc) 11.246 kB
# -*- coding: utf-8 -*-
'''
Module for gathering and managing bridging information
'''
from __future__ import absolute_import
import sys
import re
import salt.utils
__func_alias__ = {
'list_': 'list'
}
# Other BSD-like derivatives that use ifconfig may work too
SUPPORTED_BSD_LIKE = ['FreeBSD', 'NetBSD', 'OpenBSD']
def __virtual__():
'''
Confirm this module is supported by the OS and the system has
required tools
'''
supported_os_tool = {
'FreeBSD': 'ifconfig',
'Linux': 'brctl',
'NetBSD': 'brconfig',
'OpenBSD': 'ifconfig'
}
cur_os = __grains__['kernel']
for _os in supported_os_tool:
if cur_os == _os and salt.utils.which(supported_os_tool[cur_os]):
return True
return False
def _tool_path(ostool):
'''
Internal, returns tools path
'''
return salt.utils.which(ostool)
def _linux_brshow(br=None):
'''
Internal, returns bridges and enslaved interfaces (GNU/Linux - brctl)
'''
brctl = _tool_path('brctl')
if br:
cmd = '{0} show {1}'.format(brctl, br)
else:
cmd = '{0} show'.format(brctl)
brs = {}
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
# get rid of first line
if line.startswith('bridge name'):
continue
# get rid of ^\n's
vals = line.split()
if not vals:
continue
# bridge name bridge id STP enabled interfaces
# br0 8000.e4115bac8ddc no eth0
# foo0
# br1 8000.e4115bac8ddc no eth1
if len(vals) > 1:
brname = vals[0]
brs[brname] = {
'id': vals[1],
'stp': vals[2],
}
if len(vals) > 3:
brs[brname]['interfaces'] = [vals[3]]
if len(vals) == 1 and brname:
brs[brname]['interfaces'].append(vals[0])
if br:
try:
return brs[br]
except KeyError:
return None
return brs
def _linux_bradd(br):
'''
Internal, creates the bridge
'''
brctl = _tool_path('brctl')
return __salt__['cmd.run']('{0} addbr {1}'.format(brctl, br),
python_shell=False)
def _linux_brdel(br):
'''
Internal, deletes the bridge
'''
brctl = _tool_path('brctl')
return __salt__['cmd.run']('{0} delbr {1}'.format(brctl, br),
python_shell=False)
def _linux_addif(br, iface):
'''
Internal, adds an interface to a bridge
'''
brctl = _tool_path('brctl')
return __salt__['cmd.run']('{0} addif {1} {2}'.format(brctl, br, iface),
python_shell=False)
def _linux_delif(br, iface):
'''
Internal, removes an interface from a bridge
'''
brctl = _tool_path('brctl')
return __salt__['cmd.run']('{0} delif {1} {2}'.format(brctl, br, iface),
python_shell=False)
def _linux_stp(br, state):
'''
Internal, sets STP state
'''
brctl = _tool_path('brctl')
return __salt__['cmd.run']('{0} stp {1} {2}'.format(brctl, br, state),
python_shell=False)
def _bsd_brshow(br=None):
'''
Internal, returns bridges and member interfaces (BSD-like: ifconfig)
'''
if __grains__['kernel'] == 'NetBSD':
return _netbsd_brshow(br)
ifconfig = _tool_path('ifconfig')
ifaces = {}
if br:
ifaces[br] = br
else:
cmd = '{0} -g bridge'.format(ifconfig)
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
ifaces[line] = line
brs = {}
for iface in ifaces:
cmd = '{0} {1}'.format(ifconfig, iface)
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
brs[iface] = {
'interfaces': [],
'stp': 'no'
}
line = line.lstrip()
if line.startswith('member:'):
brs[iface]['interfaces'].append(line.split(' ')[1])
if 'STP' in line:
brs[iface]['stp'] = 'yes'
if br:
return brs[br]
return brs
def _netbsd_brshow(br=None):
'''
Internal, returns bridges and enslaved interfaces (NetBSD - brconfig)
'''
brconfig = _tool_path('brconfig')
if br:
cmd = '{0} {1}'.format(brconfig, br)
else:
cmd = '{0} -a'.format(brconfig)
brs = {}
start_int = False
for line in __salt__['cmd.run'](cmd, python_shell=False).splitlines():
if line.startswith('bridge'):
start_int = False
brname = line.split(':')[0] # on NetBSD, always ^bridge([0-9]+):
brs[brname] = {
'interfaces': [],
'stp': 'no'
}
if 'Interfaces:' in line:
start_int = True
continue
if start_int and brname:
m = re.match(r'\s*([a-z0-9]+)\s.*<.*>', line)
if m:
brs[brname]['interfaces'].append(m.group(1))
if 'STP' in line:
brs[brname]['stp'] = 'yes'
if br:
try:
return brs[br]
except KeyError:
return None
return brs
def _bsd_bradd(br):
'''
Internal, creates the bridge
'''
kernel = __grains__['kernel']
ifconfig = _tool_path('ifconfig')
if not br:
return False
if __salt__['cmd.retcode']('{0} {1} create up'.format(ifconfig, br),
python_shell=False) != 0:
return False
# NetBSD is two cmds
if kernel == 'NetBSD':
brconfig = _tool_path('brconfig')
if __salt__['cmd.retcode']('{0} {1} up'.format(brconfig, br),
python_shell=False) != 0:
return False
return True
def _bsd_brdel(br):
'''
Internal, deletes the bridge
'''
ifconfig = _tool_path('ifconfig')
if not br:
return False
return __salt__['cmd.run']('{0} {1} destroy'.format(ifconfig, br),
python_shell=False)
def _bsd_addif(br, iface):
'''
Internal, adds an interface to a bridge
'''
kernel = __grains__['kernel']
if kernel == 'NetBSD':
cmd = _tool_path('brconfig')
brcmd = 'add'
else:
cmd = _tool_path('ifconfig')
brcmd = 'addem'
if not br or not iface:
return False
return __salt__['cmd.run']('{0} {1} {2} {3}'.format(cmd, br, brcmd, iface),
python_shell=False)
def _bsd_delif(br, iface):
'''
Internal, removes an interface from a bridge
'''
kernel = __grains__['kernel']
if kernel == 'NetBSD':
cmd = _tool_path('brconfig')
brcmd = 'delete'
else:
cmd = _tool_path('ifconfig')
brcmd = 'deletem'
if not br or not iface:
return False
return __salt__['cmd.run']('{0} {1} {2} {3}'.format(cmd, br, brcmd, iface),
python_shell=False)
def _bsd_stp(br, state, iface):
'''
Internal, sets STP state. On BSD-like, it is required to specify the
STP physical interface
'''
kernel = __grains__['kernel']
if kernel == 'NetBSD':
cmd = _tool_path('brconfig')
else:
cmd = _tool_path('ifconfig')
if not br or not iface:
return False
return __salt__['cmd.run']('{0} {1} {2} {3}'.format(cmd, br, state, iface),
python_shell=False)
def _os_dispatch(func, *args, **kwargs):
'''
Internal, dispatches functions by operating system
'''
if __grains__['kernel'] in SUPPORTED_BSD_LIKE:
kernel = 'bsd'
else:
kernel = __grains__['kernel'].lower()
_os_func = getattr(sys.modules[__name__], '_{0}_{1}'.format(kernel, func))
if callable(_os_func):
return _os_func(*args, **kwargs)
# End of internal functions
def show(br=None):
'''
Returns bridges interfaces along with enslaved physical interfaces. If
no interface is given, all bridges are shown, else only the specified
bridge values are returned.
CLI Example:
.. code-block:: bash
salt '*' bridge.show
salt '*' bridge.show br0
'''
return _os_dispatch('brshow', br)
def list_():
'''
Returns the machine's bridges list
CLI Example:
.. code-block:: bash
salt '*' bridge.list
'''
brs = _os_dispatch('brshow')
if not brs:
return None
brlist = []
for br in brs:
brlist.append(br)
return brlist
def interfaces(br=None):
'''
Returns interfaces attached to a bridge
CLI Example:
.. code-block:: bash
salt '*' bridge.interfaces br0
'''
if not br:
return None
br_ret = _os_dispatch('brshow', br)
if br_ret:
return br_ret['interfaces']
def find_interfaces(*args):
'''
Returns the bridge to which the interfaces are bond to
CLI Example:
.. code-block:: bash
salt '*' bridge.find_interfaces eth0 [eth1...]
'''
brs = _os_dispatch('brshow')
if not brs:
return None
iflist = {}
for iface in args:
for br in brs:
try: # a bridge may not contain interfaces
if iface in brs[br]['interfaces']:
iflist[iface] = br
except Exception:
pass
return iflist
def add(br=None):
'''
Creates a bridge
CLI Example:
.. code-block:: bash
salt '*' bridge.add br0
'''
return _os_dispatch('bradd', br)
def delete(br=None):
'''
Deletes a bridge
CLI Example:
.. code-block:: bash
salt '*' bridge.delete br0
'''
return _os_dispatch('brdel', br)
def addif(br=None, iface=None):
'''
Adds an interface to a bridge
CLI Example:
.. code-block:: bash
salt '*' bridge.addif br0 eth0
'''
return _os_dispatch('addif', br, iface)
def delif(br=None, iface=None):
'''
Removes an interface from a bridge
CLI Example:
.. code-block:: bash
salt '*' bridge.delif br0 eth0
'''
return _os_dispatch('delif', br, iface)
def stp(br=None, state='disable', iface=None):
'''
Sets Spanning Tree Protocol state for a bridge
CLI Example:
.. code-block:: bash
salt '*' bridge.stp br0 enable
salt '*' bridge.stp br0 disable
For BSD-like operating systems, it is required to add the interface on
which to enable the STP.
CLI Example:
.. code-block:: bash
salt '*' bridge.stp bridge0 enable fxp0
salt '*' bridge.stp bridge0 disable fxp0
'''
kernel = __grains__['kernel']
if kernel == 'Linux':
states = {'enable': 'on', 'disable': 'off'}
return _os_dispatch('stp', br, states[state])
elif kernel in SUPPORTED_BSD_LIKE:
states = {'enable': 'stp', 'disable': '-stp'}
return _os_dispatch('stp', br, states[state], iface)
else:
return False
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
Jump to Line
Something went wrong with that request. Please try again.