Change in vdsm[master]: net: native ovs [1]
phoracek at redhat.com
phoracek at redhat.com
Wed Mar 16 15:42:30 UTC 2016
Petr Horáček has uploaded a new change for review.
Change subject: net: native ovs [1]
......................................................................
net: native ovs [1]
Basic OVS implementation.
Change-Id: I6d18b7d3e90902d29a2fdef246972a9fb1c705f1
Signed-off-by: Petr Horáček <phoracek at redhat.com>
---
M lib/vdsm/network/api.py
A lib/vdsm/network/ovs_switch/Makefile.am
A lib/vdsm/network/ovs_switch/__init__.py
A lib/vdsm/network/ovs_switch/libvirt.py
A lib/vdsm/network/ovs_switch/ovs.py
A lib/vdsm/network/ovs_switch/switch.py
A lib/vdsm/network/ovs_switch/validator.py
7 files changed, 353 insertions(+), 0 deletions(-)
git pull ssh://gerrit.ovirt.org:29418/vdsm refs/changes/21/54821/1
diff --git a/lib/vdsm/network/api.py b/lib/vdsm/network/api.py
index 74557fa..e5c4a4f 100644
--- a/lib/vdsm/network/api.py
+++ b/lib/vdsm/network/api.py
@@ -33,15 +33,20 @@
from vdsm import constants
from vdsm import hooks
from vdsm import netconfpersistence
+"""legacy
from vdsm.netinfo.cache import (libvirtNets2vdsm, get as netinfo_get,
CachingNetInfo)
from vdsm.netinfo import networks as netinfo_networks
+"""
from vdsm import udevadm
from vdsm import utils
from vdsm import ipwrapper
from . canonicalize import canonicalize_networks
+"""legacy
from . import legacy_switch
+"""
+from .ovs_switch import switch as ovs_switch
from . import errors as ne
from .configurators import RollbackIncomplete
from .errors import ConfigNetworkError
@@ -243,17 +248,23 @@
# TODO: Add canonicalize_bondings(bondings)
logging.debug('Validating configuration')
+ """legacy
legacy_switch.validate_network_setup(networks, bondings)
+ """
+ ovs_switch.validate_network_setup(networks, bondings)
bondings, networks, options = _apply_hook(bondings, networks, options)
+ """legacy
libvirt_nets = netinfo_networks()
_netinfo = CachingNetInfo(_netinfo=netinfo_get(
libvirtNets2vdsm(libvirt_nets)))
+ """
logging.debug('Applying...')
in_rollback = options.get('_inRollback', False)
with _rollback():
+ """legacy
with legacy_switch.ConfiguratorClass(in_rollback) as configurator:
# from this point forward, any exception thrown will be handled by
# Configurator.__exit__.
@@ -266,6 +277,10 @@
legacy_switch.add_missing_networks(configurator, networks,
bondings, _netinfo)
+ """
+ with ovs_switch.OvsManager(in_rollback) as manager:
+ ovs_switch.setup(networks, bondings, in_rollback,
+ manager.running_config)
_check_connectivity(networks, bondings, options)
diff --git a/lib/vdsm/network/ovs_switch/Makefile.am b/lib/vdsm/network/ovs_switch/Makefile.am
new file mode 100644
index 0000000..ca1a4b0
--- /dev/null
+++ b/lib/vdsm/network/ovs_switch/Makefile.am
@@ -0,0 +1,28 @@
+# 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
+#
+
+include $(top_srcdir)/build-aux/Makefile.subs
+
+vdsmnetworkovsswitchdir = $(vdsmpylibdir)/network/ovs_switch
+
+dist_vdsmnetworkovsswitch_PYTHON = \
+ __init__.py \
+ ovs.py \
+ switch.py \
+ $(NULL)
diff --git a/lib/vdsm/network/ovs_switch/__init__.py b/lib/vdsm/network/ovs_switch/__init__.py
new file mode 100644
index 0000000..4a67f47
--- /dev/null
+++ b/lib/vdsm/network/ovs_switch/__init__.py
@@ -0,0 +1,19 @@
+# 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
diff --git a/lib/vdsm/network/ovs_switch/libvirt.py b/lib/vdsm/network/ovs_switch/libvirt.py
new file mode 100644
index 0000000..ac27cc0
--- /dev/null
+++ b/lib/vdsm/network/ovs_switch/libvirt.py
@@ -0,0 +1,20 @@
+# 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
diff --git a/lib/vdsm/network/ovs_switch/ovs.py b/lib/vdsm/network/ovs_switch/ovs.py
new file mode 100644
index 0000000..ac27cc0
--- /dev/null
+++ b/lib/vdsm/network/ovs_switch/ovs.py
@@ -0,0 +1,20 @@
+# 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
diff --git a/lib/vdsm/network/ovs_switch/switch.py b/lib/vdsm/network/ovs_switch/switch.py
new file mode 100644
index 0000000..e94f075
--- /dev/null
+++ b/lib/vdsm/network/ovs_switch/switch.py
@@ -0,0 +1,146 @@
+# 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 logging
+
+import six
+
+from vdsm.netconfpersistence import RunningConfig
+
+from . import libvirt as _libvirt
+from . import ovs as _ovs
+from . import validator
+
+
+class RollbackIncomplete(Exception):
+ """
+ This exception is raised in order to signal API.Global that a call to
+ setupNetworks has failed and there are leftovers that need to be cleaned
+ up.
+ """
+ pass
+
+
+class RollbackManager(object): # TODO inherit interface
+ def __init__(self, in_rollback):
+ self.in_rollback = in_rollback
+
+ def __enter__(self):
+ self.running_config = RunningConfig()
+ return self
+
+ def __exit__(self, type, value, traceback):
+ if type is None:
+ self.commit()
+ elif self._in_rollback:
+ # If we failed the rollback transaction, the networking system
+ # is in no good state and we fail hard
+ logging.error('Failed rollback transaction last known good '
+ 'network.', exc_info=(type, value, traceback))
+ else:
+ leftover = self.rollback()
+ if leftover:
+ raise RollbackIncomplete(leftover, type, value)
+
+ def rollback(self):
+ """
+ Returns None when all the nets were successfully rolled back, a
+ vdsm.netoconfpersistence.Config object with the not yet rolled back
+ networks and bonds.
+ """
+ # self.runningConfig will have all the changes that were applied before
+ # we needed to rollback.
+ return RunningConfig().diffFrom(self.runningConfig)
+
+ def commit(self):
+ raise NotImplementedError
+
+
+class OvsManager(RollbackManager):
+ def commit(self):
+ self.running_config.save()
+
+
+def setup(nets, bonds, in_rollback, running_config):
+ nets_to_be_added, nets_to_be_removed = _filter_nets(nets, running_config)
+ bonds_to_be_added, bonds_to_be_removed = _filter_bonds(bonds,
+ running_config)
+
+ _ovs.remove(nets_to_be_removed, bonds_to_be_removed, running_config)
+ _libvirt.remove(nets_to_be_removed)
+ _ovs.add(nets_to_be_added, bonds_to_be_added, running_config)
+ _libvirt.add(nets_to_be_added, running_config)
+ _set_devices_up(nets_to_be_added, bonds_to_be_added)
+
+
+def _filter_nets(nets, running_config):
+ nets_to_be_removed = set()
+ nets_to_be_added = {}
+
+ for net, attrs in six.iteritems(nets):
+ if ('remove' not in attrs and
+ attrs != running_config.networks.get(net)):
+ nets_to_be_added[net] = attrs
+ if 'remove' in attrs or (
+ (net in running_config.networks and
+ attrs != running_config.networks.get(net))):
+ nets_to_be_removed.add(net)
+
+ return nets_to_be_added, nets_to_be_removed
+
+
+def _filter_bonds(bonds, running_config):
+ bonds_to_be_removed = set()
+ bonds_to_be_added = {}
+
+ for bond, attrs in six.iteritems(bonds):
+ if ('remove' not in attrs and
+ attrs != running_config.bonds.get(bond)):
+ bonds_to_be_added[bond] = attrs
+ if 'remove' in attrs:
+ bonds_to_be_removed.add(bond)
+
+ return bonds_to_be_added, bonds_to_be_removed
+
+
+def _set_devices_up(nets, bonds):
+ devices = set()
+ for net, attrs in six.iteritems(nets):
+ if 'remove' not in attrs:
+ if 'vlan' in attrs:
+ devices.add(net)
+ if 'nic' in attrs or 'bond' in attrs:
+ devices.add(attrs.get('nic') or attrs.get('bond'))
+ for bond, attrs in six.iteritems(bonds):
+ if 'remove' not in attrs:
+ devices.add(bond)
+ devices.update(attrs['nics'])
+ if ovs_bridge_exists(BRIDGE_NAME):
+ devices.add(BRIDGE_NAME)
+ for device in devices:
+ linkSet(device, ['up'])
+
+
+def validate_network_setup(nets, bonds, running_config, netinfo):
+ for net, attrs in six.iteritems(nets):
+ validator.validate_net_configuration(net, attrs, running_config,
+ netinfo)
+ for _, attrs in six.iteritems(bonds):
+ validator.validate_bond_configuration(attrs, netinfo)
diff --git a/lib/vdsm/network/ovs_switch/validator.py b/lib/vdsm/network/ovs_switch/validator.py
new file mode 100644
index 0000000..16f44c2
--- /dev/null
+++ b/lib/vdsm/network/ovs_switch/validator.py
@@ -0,0 +1,105 @@
+# Copyright 2015-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 six
+
+from vdsm.network import errors as ne
+from vdsm.network.errors import ConfigNetworkError
+
+from .utils import get_bond_options, is_ovs_bond, rget, iter_ovs_nets
+
+VALID_MODES = frozenset(['active-backup', 'balance-tcp', 'balance-slb'])
+VALID_LACP = frozenset(['active', 'passive', 'off'])
+
+
+def _get_untagged_net(running_config):
+ for net, attrs in iter_ovs_nets(running_config.networks):
+ if 'vlan' not in attrs:
+ return net
+ return None
+
+
+def validate_net_configuration(net, attrs, running_config, netinfo):
+ nic = attrs.get('nic')
+ bond = attrs.get('bonding')
+ vlan = attrs.get('vlan')
+ bridged = attrs.get('bridged', True)
+ stp = attrs.get('stp', False)
+
+ if not bridged:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_PARAMS, 'OVS does not support bridgeless networks')
+ if bond in running_config.bonds:
+ if not is_ovs_bond(running_config.bonds[bond]):
+ raise ConfigNetworkError(
+ ne.ERR_BAD_BONDING, '%s is not OVS bonding' % bond)
+ if nic is not None and nic not in netinfo.nics:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_NIC, 'Nic %s does not exist' % nic)
+ if vlan is not None and bond is None and nic is None:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_VLAN, 'You can not create a nicless/bondless vlan')
+
+ for existing_net, existing_attrs in six.iteritems(running_config.networks):
+ if (existing_net != net and
+ existing_attrs.get('nic') == nic and
+ existing_attrs.get('bond') == bond and
+ existing_attrs.get('vlan') == vlan):
+ raise ConfigNetworkError(
+ ne.ERR_BAD_PARAMS, '%s is already used by network %s' %
+ ((nic or bond), existing_net))
+ if vlan is None:
+ untagged_net = _get_untagged_net(running_config)
+ if untagged_net not in (None, net):
+ raise ConfigNetworkError(
+ ne.ERR_BAD_VLAN,
+ 'Untagged network already defined with name %s' % untagged_net)
+ if rget(attrs, ('custom', 'ovs_aa_sid')) is not None:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_PARAMS,
+ 'Cannot define aa-mapping on untagged network')
+ if stp and vlan is not None:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_PARAMS, 'STP could be set only on untagged networks')
+
+
+def validate_bond_configuration(attrs, netinfo):
+ nics = attrs.get('nics')
+ bond_options = get_bond_options(attrs.get('options'))
+
+ if nics is None or len(attrs.get('nics')) < 2:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_BONDING,
+ 'You have to define at least 2 slaves for OVS bonding')
+ for nic in nics:
+ if nic not in netinfo.nics:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_NIC, 'Nic %s does not exist' % nic)
+
+ mode = rget(bond_options, ('custom', 'ovs_mode')) or 'active-backup'
+ lacp = rget(bond_options, ('custom', 'ovs_lacp')) or 'off'
+ if mode:
+ if mode not in VALID_MODES:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_PARAMS, '%s is not valid ovs bond mode' % mode)
+ if lacp:
+ if lacp not in VALID_LACP:
+ raise ConfigNetworkError(
+ ne.ERR_BAD_PARAMS, '%s is not valid ovs lacp value' % lacp)
--
To view, visit https://gerrit.ovirt.org/54821
To unsubscribe, visit https://gerrit.ovirt.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6d18b7d3e90902d29a2fdef246972a9fb1c705f1
Gerrit-PatchSet: 1
Gerrit-Project: vdsm
Gerrit-Branch: master
Gerrit-Owner: Petr Horáček <phoracek at redhat.com>
More information about the vdsm-patches
mailing list