]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Moves ovs_lib to agent/common
authorAdelina Tuvenie <atuvenie@cloudbasesolutions.com>
Tue, 24 Mar 2015 16:29:45 +0000 (09:29 -0700)
committerAdelina Tuvenie <atuvenie@cloudbasesolutions.com>
Wed, 25 Mar 2015 20:48:33 +0000 (13:48 -0700)
This patch moves ovs_lib from agent/linux to agent/common
since it will be used by ovs_neutron_agent on both Linux
and Windows platforms. To provide compatibility with out of
tree code, a placeholder has been left in agent/linux.

Unit tests are updated accordingly.

Partially implements blueprint: hyper-v-ovs-agent

Change-Id: I009f7f5e3b014633541ed5a45628aa1b2287e22b

21 files changed:
neutron/agent/common/ovs_lib.py [new file with mode: 0644]
neutron/agent/linux/interface.py
neutron/agent/linux/ovs_lib.py
neutron/agent/ovsdb/impl_idl.py
neutron/cmd/netns_cleanup.py
neutron/cmd/ovs_cleanup.py
neutron/cmd/sanity/checks.py
neutron/plugins/ibm/agent/sdnve_neutron_agent.py
neutron/plugins/oneconvergence/agent/nvsd_neutron_agent.py
neutron/plugins/openvswitch/agent/ovs_neutron_agent.py
neutron/tests/functional/agent/linux/base.py
neutron/tests/functional/agent/test_l3_agent.py [changed mode: 0755->0644]
neutron/tests/functional/agent/test_ovs_lib.py
neutron/tests/unit/agent/common/test_ovs_lib.py [moved from neutron/tests/unit/agent/linux/test_ovs_lib.py with 99% similarity]
neutron/tests/unit/oneconvergence/test_nvsd_agent.py
neutron/tests/unit/openvswitch/test_ovs_dvr_neutron_agent.py
neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py
neutron/tests/unit/openvswitch/test_ovs_tunnel.py
neutron/tests/unit/test_linux_interface.py
neutron/tests/unit/test_netns_cleanup.py
neutron/tests/unit/test_ovs_cleanup.py

diff --git a/neutron/agent/common/ovs_lib.py b/neutron/agent/common/ovs_lib.py
new file mode 100644 (file)
index 0000000..8ab1888
--- /dev/null
@@ -0,0 +1,524 @@
+# Copyright 2011 VMware, Inc.
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+import collections
+import itertools
+import operator
+
+from oslo_config import cfg
+from oslo_log import log as logging
+from oslo_utils import excutils
+import retrying
+import six
+
+from neutron.agent.linux import ip_lib
+from neutron.agent.linux import utils
+from neutron.agent.ovsdb import api as ovsdb
+from neutron.common import exceptions
+from neutron.i18n import _LE, _LI, _LW
+from neutron.plugins.common import constants
+
+# Default timeout for ovs-vsctl command
+DEFAULT_OVS_VSCTL_TIMEOUT = 10
+
+# Special return value for an invalid OVS ofport
+INVALID_OFPORT = -1
+UNASSIGNED_OFPORT = []
+
+# OVS bridge fail modes
+FAILMODE_SECURE = 'secure'
+
+OPTS = [
+    cfg.IntOpt('ovs_vsctl_timeout',
+               default=DEFAULT_OVS_VSCTL_TIMEOUT,
+               help=_('Timeout in seconds for ovs-vsctl commands')),
+]
+cfg.CONF.register_opts(OPTS)
+
+LOG = logging.getLogger(__name__)
+
+
+def _ofport_result_pending(result):
+    """Return True if ovs-vsctl indicates the result is still pending."""
+    # ovs-vsctl can return '[]' for an ofport that has not yet been assigned
+    try:
+        int(result)
+        return False
+    except (ValueError, TypeError):
+        return True
+
+
+def _ofport_retry(fn):
+    """Decorator for retrying when OVS has yet to assign an ofport.
+
+    The instance's vsctl_timeout is used as the max waiting time. This relies
+    on the fact that instance methods receive self as the first argument.
+    """
+    @six.wraps(fn)
+    def wrapped(*args, **kwargs):
+        self = args[0]
+        new_fn = retrying.retry(
+            retry_on_result=_ofport_result_pending,
+            stop_max_delay=self.vsctl_timeout * 1000,
+            wait_exponential_multiplier=10,
+            wait_exponential_max=1000,
+            retry_on_exception=lambda _: False)(fn)
+        return new_fn(*args, **kwargs)
+    return wrapped
+
+
+class VifPort(object):
+    def __init__(self, port_name, ofport, vif_id, vif_mac, switch):
+        self.port_name = port_name
+        self.ofport = ofport
+        self.vif_id = vif_id
+        self.vif_mac = vif_mac
+        self.switch = switch
+
+    def __str__(self):
+        return ("iface-id=" + self.vif_id + ", vif_mac=" +
+                self.vif_mac + ", port_name=" + self.port_name +
+                ", ofport=" + str(self.ofport) + ", bridge_name=" +
+                self.switch.br_name)
+
+
+class BaseOVS(object):
+
+    def __init__(self):
+        self.vsctl_timeout = cfg.CONF.ovs_vsctl_timeout
+        self.ovsdb = ovsdb.API.get(self)
+
+    def add_bridge(self, bridge_name):
+        self.ovsdb.add_br(bridge_name).execute()
+        br = OVSBridge(bridge_name)
+        # Don't return until vswitchd sets up the internal port
+        br.get_port_ofport(bridge_name)
+        return br
+
+    def delete_bridge(self, bridge_name):
+        self.ovsdb.del_br(bridge_name).execute()
+
+    def bridge_exists(self, bridge_name):
+        return self.ovsdb.br_exists(bridge_name).execute()
+
+    def port_exists(self, port_name):
+        cmd = self.ovsdb.db_get('Port', port_name, 'name')
+        return bool(cmd.execute(check_error=False, log_errors=False))
+
+    def get_bridge_for_iface(self, iface):
+        return self.ovsdb.iface_to_br(iface).execute()
+
+    def get_bridges(self):
+        return self.ovsdb.list_br().execute(check_error=True)
+
+    def get_bridge_external_bridge_id(self, bridge):
+        return self.ovsdb.br_get_external_id(bridge, 'bridge-id').execute()
+
+    def set_db_attribute(self, table_name, record, column, value,
+                         check_error=False):
+        self.ovsdb.db_set(table_name, record, (column, value)).execute(
+            check_error=check_error)
+
+    def clear_db_attribute(self, table_name, record, column):
+        self.ovsdb.db_clear(table_name, record, column).execute()
+
+    def db_get_val(self, table, record, column, check_error=False):
+        return self.ovsdb.db_get(table, record, column).execute(
+            check_error=check_error)
+
+
+class OVSBridge(BaseOVS):
+    def __init__(self, br_name):
+        super(OVSBridge, self).__init__()
+        self.br_name = br_name
+
+    def set_controller(self, controllers):
+        self.ovsdb.set_controller(self.br_name,
+                                  controllers).execute(check_error=True)
+
+    def del_controller(self):
+        self.ovsdb.del_controller(self.br_name).execute(check_error=True)
+
+    def get_controller(self):
+        return self.ovsdb.get_controller(self.br_name).execute(
+            check_error=True)
+
+    def set_secure_mode(self):
+        self.ovsdb.set_fail_mode(self.br_name, FAILMODE_SECURE).execute(
+            check_error=True)
+
+    def set_protocols(self, protocols):
+        self.set_db_attribute('Bridge', self.br_name, 'protocols', protocols,
+                              check_error=True)
+
+    def create(self):
+        self.ovsdb.add_br(self.br_name).execute()
+        # Don't return until vswitchd sets up the internal port
+        self.get_port_ofport(self.br_name)
+
+    def destroy(self):
+        self.delete_bridge(self.br_name)
+
+    def reset_bridge(self, secure_mode=False):
+        with self.ovsdb.transaction() as txn:
+            txn.add(self.ovsdb.del_br(self.br_name))
+            txn.add(self.ovsdb.add_br(self.br_name))
+            if secure_mode:
+                txn.add(self.ovsdb.set_fail_mode(self.br_name,
+                                                 FAILMODE_SECURE))
+
+    def add_port(self, port_name, *interface_attr_tuples):
+        with self.ovsdb.transaction() as txn:
+            txn.add(self.ovsdb.add_port(self.br_name, port_name))
+            if interface_attr_tuples:
+                txn.add(self.ovsdb.db_set('Interface', port_name,
+                                          *interface_attr_tuples))
+        return self.get_port_ofport(port_name)
+
+    def replace_port(self, port_name, *interface_attr_tuples):
+        """Replace existing port or create it, and configure port interface."""
+        with self.ovsdb.transaction() as txn:
+            txn.add(self.ovsdb.del_port(port_name))
+            txn.add(self.ovsdb.add_port(self.br_name, port_name,
+                                        may_exist=False))
+            if interface_attr_tuples:
+                txn.add(self.ovsdb.db_set('Interface', port_name,
+                                          *interface_attr_tuples))
+        # Don't return until the port has been assigned by vswitchd
+        self.get_port_ofport(port_name)
+
+    def delete_port(self, port_name):
+        self.ovsdb.del_port(port_name, self.br_name).execute()
+
+    def run_ofctl(self, cmd, args, process_input=None):
+        full_args = ["ovs-ofctl", cmd, self.br_name] + args
+        try:
+            return utils.execute(full_args, run_as_root=True,
+                                 process_input=process_input)
+        except Exception as e:
+            LOG.error(_LE("Unable to execute %(cmd)s. Exception: "
+                          "%(exception)s"),
+                      {'cmd': full_args, 'exception': e})
+
+    def count_flows(self):
+        flow_list = self.run_ofctl("dump-flows", []).split("\n")[1:]
+        return len(flow_list) - 1
+
+    def remove_all_flows(self):
+        self.run_ofctl("del-flows", [])
+
+    @_ofport_retry
+    def _get_port_ofport(self, port_name):
+        return self.db_get_val("Interface", port_name, "ofport")
+
+    def get_port_ofport(self, port_name):
+        """Get the port's assigned ofport, retrying if not yet assigned."""
+        ofport = INVALID_OFPORT
+        try:
+            ofport = self._get_port_ofport(port_name)
+        except retrying.RetryError as e:
+            LOG.exception(_LE("Timed out retrieving ofport on port %(pname)s. "
+                              "Exception: %(exception)s"),
+                          {'pname': port_name, 'exception': e})
+        return ofport
+
+    def get_datapath_id(self):
+        return self.db_get_val('Bridge',
+                               self.br_name, 'datapath_id')
+
+    def do_action_flows(self, action, kwargs_list):
+        flow_strs = [_build_flow_expr_str(kw, action) for kw in kwargs_list]
+        self.run_ofctl('%s-flows' % action, ['-'], '\n'.join(flow_strs))
+
+    def add_flow(self, **kwargs):
+        self.do_action_flows('add', [kwargs])
+
+    def mod_flow(self, **kwargs):
+        self.do_action_flows('mod', [kwargs])
+
+    def delete_flows(self, **kwargs):
+        self.do_action_flows('del', [kwargs])
+
+    def dump_flows_for_table(self, table):
+        retval = None
+        flow_str = "table=%s" % table
+        flows = self.run_ofctl("dump-flows", [flow_str])
+        if flows:
+            retval = '\n'.join(item for item in flows.splitlines()
+                               if 'NXST' not in item)
+        return retval
+
+    def deferred(self, **kwargs):
+        return DeferredOVSBridge(self, **kwargs)
+
+    def add_tunnel_port(self, port_name, remote_ip, local_ip,
+                        tunnel_type=constants.TYPE_GRE,
+                        vxlan_udp_port=constants.VXLAN_UDP_PORT,
+                        dont_fragment=True):
+        attrs = [('type', tunnel_type)]
+        # TODO(twilson) This is an OrderedDict solely to make a test happy
+        options = collections.OrderedDict()
+        vxlan_uses_custom_udp_port = (
+            tunnel_type == constants.TYPE_VXLAN and
+            vxlan_udp_port != constants.VXLAN_UDP_PORT
+        )
+        if vxlan_uses_custom_udp_port:
+            options['dst_port'] = vxlan_udp_port
+        options['df_default'] = str(dont_fragment).lower()
+        options['remote_ip'] = remote_ip
+        options['local_ip'] = local_ip
+        options['in_key'] = 'flow'
+        options['out_key'] = 'flow'
+        attrs.append(('options', options))
+
+        return self.add_port(port_name, *attrs)
+
+    def add_patch_port(self, local_name, remote_name):
+        attrs = [('type', 'patch'),
+                 ('options', {'peer': remote_name})]
+        return self.add_port(local_name, *attrs)
+
+    def get_port_name_list(self):
+        return self.ovsdb.list_ports(self.br_name).execute(check_error=True)
+
+    def get_port_stats(self, port_name):
+        return self.db_get_val("Interface", port_name, "statistics")
+
+    def get_xapi_iface_id(self, xs_vif_uuid):
+        args = ["xe", "vif-param-get", "param-name=other-config",
+                "param-key=nicira-iface-id", "uuid=%s" % xs_vif_uuid]
+        try:
+            return utils.execute(args, run_as_root=True).strip()
+        except Exception as e:
+            with excutils.save_and_reraise_exception():
+                LOG.error(_LE("Unable to execute %(cmd)s. "
+                              "Exception: %(exception)s"),
+                          {'cmd': args, 'exception': e})
+
+    # returns a VIF object for each VIF port
+    def get_vif_ports(self):
+        edge_ports = []
+        port_names = self.get_port_name_list()
+        for name in port_names:
+            external_ids = self.db_get_val("Interface", name, "external_ids",
+                                           check_error=True)
+            ofport = self.db_get_val("Interface", name, "ofport",
+                                     check_error=True)
+            if "iface-id" in external_ids and "attached-mac" in external_ids:
+                p = VifPort(name, ofport, external_ids["iface-id"],
+                            external_ids["attached-mac"], self)
+                edge_ports.append(p)
+            elif ("xs-vif-uuid" in external_ids and
+                  "attached-mac" in external_ids):
+                # if this is a xenserver and iface-id is not automatically
+                # synced to OVS from XAPI, we grab it from XAPI directly
+                iface_id = self.get_xapi_iface_id(external_ids["xs-vif-uuid"])
+                p = VifPort(name, ofport, iface_id,
+                            external_ids["attached-mac"], self)
+                edge_ports.append(p)
+
+        return edge_ports
+
+    def get_vif_port_set(self):
+        edge_ports = set()
+        port_names = self.get_port_name_list()
+        cmd = self.ovsdb.db_list(
+            'Interface', port_names,
+            columns=['name', 'external_ids', 'ofport'], if_exists=True)
+        results = cmd.execute(check_error=True)
+        for result in results:
+            if result['ofport'] == UNASSIGNED_OFPORT:
+                LOG.warn(_LW("Found not yet ready openvswitch port: %s"),
+                         result['name'])
+            elif result['ofport'] == INVALID_OFPORT:
+                LOG.warn(_LW("Found failed openvswitch port: %s"),
+                         result['name'])
+            elif 'attached-mac' in result['external_ids']:
+                external_ids = result['external_ids']
+                if 'iface-id' in external_ids:
+                    edge_ports.add(external_ids['iface-id'])
+                elif 'xs-vif-uuid' in external_ids:
+                    iface_id = self.get_xapi_iface_id(
+                        external_ids['xs-vif-uuid'])
+                    edge_ports.add(iface_id)
+        return edge_ports
+
+    def get_port_tag_dict(self):
+        """Get a dict of port names and associated vlan tags.
+
+        e.g. the returned dict is of the following form::
+
+            {u'int-br-eth2': [],
+             u'patch-tun': [],
+             u'qr-76d9e6b6-21': 1,
+             u'tapce5318ff-78': 1,
+             u'tape1400310-e6': 1}
+
+        The TAG ID is only available in the "Port" table and is not available
+        in the "Interface" table queried by the get_vif_port_set() method.
+
+        """
+        port_names = self.get_port_name_list()
+        cmd = self.ovsdb.db_list('Port', port_names, columns=['name', 'tag'])
+        results = cmd.execute(check_error=True)
+        return {p['name']: p['tag'] for p in results}
+
+    def get_vif_port_by_id(self, port_id):
+        ports = self.ovsdb.db_find(
+            'Interface', ('external_ids', '=', {'iface-id': port_id}),
+            ('external_ids', '!=', {'attached-mac': ''}),
+            columns=['external_ids', 'name', 'ofport']).execute()
+        for port in ports:
+            if self.br_name != self.get_bridge_for_iface(port['name']):
+                continue
+            if port['ofport'] in [UNASSIGNED_OFPORT, INVALID_OFPORT]:
+                LOG.warn(_LW("ofport: %(ofport)s for VIF: %(vif)s is not a"
+                             " positive integer"),
+                         {'ofport': port['ofport'], 'vif': port_id})
+                continue
+            mac = port['external_ids'].get('attached-mac')
+            return VifPort(port['name'], port['ofport'], port_id, mac, self)
+        LOG.info(_LI("Port %(port_id)s not present in bridge %(br_name)s"),
+                 {'port_id': port_id, 'br_name': self.br_name})
+
+    def delete_ports(self, all_ports=False):
+        if all_ports:
+            port_names = self.get_port_name_list()
+        else:
+            port_names = (port.port_name for port in self.get_vif_ports())
+
+        for port_name in port_names:
+            self.delete_port(port_name)
+
+    def get_local_port_mac(self):
+        """Retrieve the mac of the bridge's local port."""
+        address = ip_lib.IPDevice(self.br_name).link.address
+        if address:
+            return address
+        else:
+            msg = _('Unable to determine mac address for %s') % self.br_name
+            raise Exception(msg)
+
+    def __enter__(self):
+        self.create()
+        return self
+
+    def __exit__(self, exc_type, exc_value, exc_tb):
+        self.destroy()
+
+
+class DeferredOVSBridge(object):
+    '''Deferred OVSBridge.
+
+    This class wraps add_flow, mod_flow and delete_flows calls to an OVSBridge
+    and defers their application until apply_flows call in order to perform
+    bulk calls. It wraps also ALLOWED_PASSTHROUGHS calls to avoid mixing
+    OVSBridge and DeferredOVSBridge uses.
+    This class can be used as a context, in such case apply_flows is called on
+    __exit__ except if an exception is raised.
+    This class is not thread-safe, that's why for every use a new instance
+    must be implemented.
+    '''
+    ALLOWED_PASSTHROUGHS = 'add_port', 'add_tunnel_port', 'delete_port'
+
+    def __init__(self, br, full_ordered=False,
+                 order=('add', 'mod', 'del')):
+        '''Constructor.
+
+        :param br: wrapped bridge
+        :param full_ordered: Optional, disable flow reordering (slower)
+        :param order: Optional, define in which order flow are applied
+        '''
+
+        self.br = br
+        self.full_ordered = full_ordered
+        self.order = order
+        if not self.full_ordered:
+            self.weights = dict((y, x) for x, y in enumerate(self.order))
+        self.action_flow_tuples = []
+
+    def __getattr__(self, name):
+        if name in self.ALLOWED_PASSTHROUGHS:
+            return getattr(self.br, name)
+        raise AttributeError(name)
+
+    def add_flow(self, **kwargs):
+        self.action_flow_tuples.append(('add', kwargs))
+
+    def mod_flow(self, **kwargs):
+        self.action_flow_tuples.append(('mod', kwargs))
+
+    def delete_flows(self, **kwargs):
+        self.action_flow_tuples.append(('del', kwargs))
+
+    def apply_flows(self):
+        action_flow_tuples = self.action_flow_tuples
+        self.action_flow_tuples = []
+        if not action_flow_tuples:
+            return
+
+        if not self.full_ordered:
+            action_flow_tuples.sort(key=lambda af: self.weights[af[0]])
+
+        grouped = itertools.groupby(action_flow_tuples,
+                                    key=operator.itemgetter(0))
+        itemgetter_1 = operator.itemgetter(1)
+        for action, action_flow_list in grouped:
+            flows = map(itemgetter_1, action_flow_list)
+            self.br.do_action_flows(action, flows)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        if exc_type is None:
+            self.apply_flows()
+        else:
+            LOG.exception(_LE("OVS flows could not be applied on bridge %s"),
+                          self.br.br_name)
+
+
+def _build_flow_expr_str(flow_dict, cmd):
+    flow_expr_arr = []
+    actions = None
+
+    if cmd == 'add':
+        flow_expr_arr.append("hard_timeout=%s" %
+                             flow_dict.pop('hard_timeout', '0'))
+        flow_expr_arr.append("idle_timeout=%s" %
+                             flow_dict.pop('idle_timeout', '0'))
+        flow_expr_arr.append("priority=%s" %
+                             flow_dict.pop('priority', '1'))
+    elif 'priority' in flow_dict:
+        msg = _("Cannot match priority on flow deletion or modification")
+        raise exceptions.InvalidInput(error_message=msg)
+
+    if cmd != 'del':
+        if "actions" not in flow_dict:
+            msg = _("Must specify one or more actions on flow addition"
+                    " or modification")
+            raise exceptions.InvalidInput(error_message=msg)
+        actions = "actions=%s" % flow_dict.pop('actions')
+
+    for key, value in flow_dict.iteritems():
+        if key == 'proto':
+            flow_expr_arr.append(value)
+        else:
+            flow_expr_arr.append("%s=%s" % (key, str(value)))
+
+    if actions:
+        flow_expr_arr.append(actions)
+
+    return ','.join(flow_expr_arr)
index d3eb2f10c8f1a85aaeaa7d0190f92128f720f617..43f8b091f3a43f70f4b5325854186dad45c4ae4f 100644 (file)
@@ -21,8 +21,8 @@ from oslo_log import log as logging
 from oslo_utils import importutils
 import six
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.agent.linux import utils
 from neutron.common import constants as n_const
 from neutron.common import exceptions
index 8ab1888bc015b008343bc654419ddbc5b4bebcb1..13a79dcf87938b2c7f61a3e0ac25b17bec4fba60 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011 VMware, Inc.
+# Copyright 2015 Cloudbase Solutions.
 # All Rights Reserved.
 #
 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import collections
-import itertools
-import operator
+# This is a placeholder so that the vendor code that import the ovs_lib
+# module from agent/linux doesn't fail
+# TODO(atuvenie) remove this module after opening the liberty cycle
 
-from oslo_config import cfg
-from oslo_log import log as logging
-from oslo_utils import excutils
-import retrying
-import six
+from neutron.agent.common import ovs_lib
 
-from neutron.agent.linux import ip_lib
-from neutron.agent.linux import utils
-from neutron.agent.ovsdb import api as ovsdb
-from neutron.common import exceptions
-from neutron.i18n import _LE, _LI, _LW
-from neutron.plugins.common import constants
-
-# Default timeout for ovs-vsctl command
-DEFAULT_OVS_VSCTL_TIMEOUT = 10
-
-# Special return value for an invalid OVS ofport
-INVALID_OFPORT = -1
-UNASSIGNED_OFPORT = []
-
-# OVS bridge fail modes
-FAILMODE_SECURE = 'secure'
-
-OPTS = [
-    cfg.IntOpt('ovs_vsctl_timeout',
-               default=DEFAULT_OVS_VSCTL_TIMEOUT,
-               help=_('Timeout in seconds for ovs-vsctl commands')),
-]
-cfg.CONF.register_opts(OPTS)
-
-LOG = logging.getLogger(__name__)
-
-
-def _ofport_result_pending(result):
-    """Return True if ovs-vsctl indicates the result is still pending."""
-    # ovs-vsctl can return '[]' for an ofport that has not yet been assigned
-    try:
-        int(result)
-        return False
-    except (ValueError, TypeError):
-        return True
-
-
-def _ofport_retry(fn):
-    """Decorator for retrying when OVS has yet to assign an ofport.
-
-    The instance's vsctl_timeout is used as the max waiting time. This relies
-    on the fact that instance methods receive self as the first argument.
-    """
-    @six.wraps(fn)
-    def wrapped(*args, **kwargs):
-        self = args[0]
-        new_fn = retrying.retry(
-            retry_on_result=_ofport_result_pending,
-            stop_max_delay=self.vsctl_timeout * 1000,
-            wait_exponential_multiplier=10,
-            wait_exponential_max=1000,
-            retry_on_exception=lambda _: False)(fn)
-        return new_fn(*args, **kwargs)
-    return wrapped
-
-
-class VifPort(object):
-    def __init__(self, port_name, ofport, vif_id, vif_mac, switch):
-        self.port_name = port_name
-        self.ofport = ofport
-        self.vif_id = vif_id
-        self.vif_mac = vif_mac
-        self.switch = switch
-
-    def __str__(self):
-        return ("iface-id=" + self.vif_id + ", vif_mac=" +
-                self.vif_mac + ", port_name=" + self.port_name +
-                ", ofport=" + str(self.ofport) + ", bridge_name=" +
-                self.switch.br_name)
-
-
-class BaseOVS(object):
-
-    def __init__(self):
-        self.vsctl_timeout = cfg.CONF.ovs_vsctl_timeout
-        self.ovsdb = ovsdb.API.get(self)
-
-    def add_bridge(self, bridge_name):
-        self.ovsdb.add_br(bridge_name).execute()
-        br = OVSBridge(bridge_name)
-        # Don't return until vswitchd sets up the internal port
-        br.get_port_ofport(bridge_name)
-        return br
-
-    def delete_bridge(self, bridge_name):
-        self.ovsdb.del_br(bridge_name).execute()
-
-    def bridge_exists(self, bridge_name):
-        return self.ovsdb.br_exists(bridge_name).execute()
-
-    def port_exists(self, port_name):
-        cmd = self.ovsdb.db_get('Port', port_name, 'name')
-        return bool(cmd.execute(check_error=False, log_errors=False))
-
-    def get_bridge_for_iface(self, iface):
-        return self.ovsdb.iface_to_br(iface).execute()
-
-    def get_bridges(self):
-        return self.ovsdb.list_br().execute(check_error=True)
-
-    def get_bridge_external_bridge_id(self, bridge):
-        return self.ovsdb.br_get_external_id(bridge, 'bridge-id').execute()
-
-    def set_db_attribute(self, table_name, record, column, value,
-                         check_error=False):
-        self.ovsdb.db_set(table_name, record, (column, value)).execute(
-            check_error=check_error)
-
-    def clear_db_attribute(self, table_name, record, column):
-        self.ovsdb.db_clear(table_name, record, column).execute()
-
-    def db_get_val(self, table, record, column, check_error=False):
-        return self.ovsdb.db_get(table, record, column).execute(
-            check_error=check_error)
-
-
-class OVSBridge(BaseOVS):
-    def __init__(self, br_name):
-        super(OVSBridge, self).__init__()
-        self.br_name = br_name
-
-    def set_controller(self, controllers):
-        self.ovsdb.set_controller(self.br_name,
-                                  controllers).execute(check_error=True)
-
-    def del_controller(self):
-        self.ovsdb.del_controller(self.br_name).execute(check_error=True)
-
-    def get_controller(self):
-        return self.ovsdb.get_controller(self.br_name).execute(
-            check_error=True)
-
-    def set_secure_mode(self):
-        self.ovsdb.set_fail_mode(self.br_name, FAILMODE_SECURE).execute(
-            check_error=True)
-
-    def set_protocols(self, protocols):
-        self.set_db_attribute('Bridge', self.br_name, 'protocols', protocols,
-                              check_error=True)
-
-    def create(self):
-        self.ovsdb.add_br(self.br_name).execute()
-        # Don't return until vswitchd sets up the internal port
-        self.get_port_ofport(self.br_name)
-
-    def destroy(self):
-        self.delete_bridge(self.br_name)
-
-    def reset_bridge(self, secure_mode=False):
-        with self.ovsdb.transaction() as txn:
-            txn.add(self.ovsdb.del_br(self.br_name))
-            txn.add(self.ovsdb.add_br(self.br_name))
-            if secure_mode:
-                txn.add(self.ovsdb.set_fail_mode(self.br_name,
-                                                 FAILMODE_SECURE))
-
-    def add_port(self, port_name, *interface_attr_tuples):
-        with self.ovsdb.transaction() as txn:
-            txn.add(self.ovsdb.add_port(self.br_name, port_name))
-            if interface_attr_tuples:
-                txn.add(self.ovsdb.db_set('Interface', port_name,
-                                          *interface_attr_tuples))
-        return self.get_port_ofport(port_name)
-
-    def replace_port(self, port_name, *interface_attr_tuples):
-        """Replace existing port or create it, and configure port interface."""
-        with self.ovsdb.transaction() as txn:
-            txn.add(self.ovsdb.del_port(port_name))
-            txn.add(self.ovsdb.add_port(self.br_name, port_name,
-                                        may_exist=False))
-            if interface_attr_tuples:
-                txn.add(self.ovsdb.db_set('Interface', port_name,
-                                          *interface_attr_tuples))
-        # Don't return until the port has been assigned by vswitchd
-        self.get_port_ofport(port_name)
-
-    def delete_port(self, port_name):
-        self.ovsdb.del_port(port_name, self.br_name).execute()
-
-    def run_ofctl(self, cmd, args, process_input=None):
-        full_args = ["ovs-ofctl", cmd, self.br_name] + args
-        try:
-            return utils.execute(full_args, run_as_root=True,
-                                 process_input=process_input)
-        except Exception as e:
-            LOG.error(_LE("Unable to execute %(cmd)s. Exception: "
-                          "%(exception)s"),
-                      {'cmd': full_args, 'exception': e})
-
-    def count_flows(self):
-        flow_list = self.run_ofctl("dump-flows", []).split("\n")[1:]
-        return len(flow_list) - 1
-
-    def remove_all_flows(self):
-        self.run_ofctl("del-flows", [])
-
-    @_ofport_retry
-    def _get_port_ofport(self, port_name):
-        return self.db_get_val("Interface", port_name, "ofport")
-
-    def get_port_ofport(self, port_name):
-        """Get the port's assigned ofport, retrying if not yet assigned."""
-        ofport = INVALID_OFPORT
-        try:
-            ofport = self._get_port_ofport(port_name)
-        except retrying.RetryError as e:
-            LOG.exception(_LE("Timed out retrieving ofport on port %(pname)s. "
-                              "Exception: %(exception)s"),
-                          {'pname': port_name, 'exception': e})
-        return ofport
-
-    def get_datapath_id(self):
-        return self.db_get_val('Bridge',
-                               self.br_name, 'datapath_id')
-
-    def do_action_flows(self, action, kwargs_list):
-        flow_strs = [_build_flow_expr_str(kw, action) for kw in kwargs_list]
-        self.run_ofctl('%s-flows' % action, ['-'], '\n'.join(flow_strs))
-
-    def add_flow(self, **kwargs):
-        self.do_action_flows('add', [kwargs])
-
-    def mod_flow(self, **kwargs):
-        self.do_action_flows('mod', [kwargs])
-
-    def delete_flows(self, **kwargs):
-        self.do_action_flows('del', [kwargs])
-
-    def dump_flows_for_table(self, table):
-        retval = None
-        flow_str = "table=%s" % table
-        flows = self.run_ofctl("dump-flows", [flow_str])
-        if flows:
-            retval = '\n'.join(item for item in flows.splitlines()
-                               if 'NXST' not in item)
-        return retval
-
-    def deferred(self, **kwargs):
-        return DeferredOVSBridge(self, **kwargs)
-
-    def add_tunnel_port(self, port_name, remote_ip, local_ip,
-                        tunnel_type=constants.TYPE_GRE,
-                        vxlan_udp_port=constants.VXLAN_UDP_PORT,
-                        dont_fragment=True):
-        attrs = [('type', tunnel_type)]
-        # TODO(twilson) This is an OrderedDict solely to make a test happy
-        options = collections.OrderedDict()
-        vxlan_uses_custom_udp_port = (
-            tunnel_type == constants.TYPE_VXLAN and
-            vxlan_udp_port != constants.VXLAN_UDP_PORT
-        )
-        if vxlan_uses_custom_udp_port:
-            options['dst_port'] = vxlan_udp_port
-        options['df_default'] = str(dont_fragment).lower()
-        options['remote_ip'] = remote_ip
-        options['local_ip'] = local_ip
-        options['in_key'] = 'flow'
-        options['out_key'] = 'flow'
-        attrs.append(('options', options))
-
-        return self.add_port(port_name, *attrs)
-
-    def add_patch_port(self, local_name, remote_name):
-        attrs = [('type', 'patch'),
-                 ('options', {'peer': remote_name})]
-        return self.add_port(local_name, *attrs)
-
-    def get_port_name_list(self):
-        return self.ovsdb.list_ports(self.br_name).execute(check_error=True)
-
-    def get_port_stats(self, port_name):
-        return self.db_get_val("Interface", port_name, "statistics")
-
-    def get_xapi_iface_id(self, xs_vif_uuid):
-        args = ["xe", "vif-param-get", "param-name=other-config",
-                "param-key=nicira-iface-id", "uuid=%s" % xs_vif_uuid]
-        try:
-            return utils.execute(args, run_as_root=True).strip()
-        except Exception as e:
-            with excutils.save_and_reraise_exception():
-                LOG.error(_LE("Unable to execute %(cmd)s. "
-                              "Exception: %(exception)s"),
-                          {'cmd': args, 'exception': e})
-
-    # returns a VIF object for each VIF port
-    def get_vif_ports(self):
-        edge_ports = []
-        port_names = self.get_port_name_list()
-        for name in port_names:
-            external_ids = self.db_get_val("Interface", name, "external_ids",
-                                           check_error=True)
-            ofport = self.db_get_val("Interface", name, "ofport",
-                                     check_error=True)
-            if "iface-id" in external_ids and "attached-mac" in external_ids:
-                p = VifPort(name, ofport, external_ids["iface-id"],
-                            external_ids["attached-mac"], self)
-                edge_ports.append(p)
-            elif ("xs-vif-uuid" in external_ids and
-                  "attached-mac" in external_ids):
-                # if this is a xenserver and iface-id is not automatically
-                # synced to OVS from XAPI, we grab it from XAPI directly
-                iface_id = self.get_xapi_iface_id(external_ids["xs-vif-uuid"])
-                p = VifPort(name, ofport, iface_id,
-                            external_ids["attached-mac"], self)
-                edge_ports.append(p)
-
-        return edge_ports
-
-    def get_vif_port_set(self):
-        edge_ports = set()
-        port_names = self.get_port_name_list()
-        cmd = self.ovsdb.db_list(
-            'Interface', port_names,
-            columns=['name', 'external_ids', 'ofport'], if_exists=True)
-        results = cmd.execute(check_error=True)
-        for result in results:
-            if result['ofport'] == UNASSIGNED_OFPORT:
-                LOG.warn(_LW("Found not yet ready openvswitch port: %s"),
-                         result['name'])
-            elif result['ofport'] == INVALID_OFPORT:
-                LOG.warn(_LW("Found failed openvswitch port: %s"),
-                         result['name'])
-            elif 'attached-mac' in result['external_ids']:
-                external_ids = result['external_ids']
-                if 'iface-id' in external_ids:
-                    edge_ports.add(external_ids['iface-id'])
-                elif 'xs-vif-uuid' in external_ids:
-                    iface_id = self.get_xapi_iface_id(
-                        external_ids['xs-vif-uuid'])
-                    edge_ports.add(iface_id)
-        return edge_ports
-
-    def get_port_tag_dict(self):
-        """Get a dict of port names and associated vlan tags.
-
-        e.g. the returned dict is of the following form::
-
-            {u'int-br-eth2': [],
-             u'patch-tun': [],
-             u'qr-76d9e6b6-21': 1,
-             u'tapce5318ff-78': 1,
-             u'tape1400310-e6': 1}
-
-        The TAG ID is only available in the "Port" table and is not available
-        in the "Interface" table queried by the get_vif_port_set() method.
-
-        """
-        port_names = self.get_port_name_list()
-        cmd = self.ovsdb.db_list('Port', port_names, columns=['name', 'tag'])
-        results = cmd.execute(check_error=True)
-        return {p['name']: p['tag'] for p in results}
-
-    def get_vif_port_by_id(self, port_id):
-        ports = self.ovsdb.db_find(
-            'Interface', ('external_ids', '=', {'iface-id': port_id}),
-            ('external_ids', '!=', {'attached-mac': ''}),
-            columns=['external_ids', 'name', 'ofport']).execute()
-        for port in ports:
-            if self.br_name != self.get_bridge_for_iface(port['name']):
-                continue
-            if port['ofport'] in [UNASSIGNED_OFPORT, INVALID_OFPORT]:
-                LOG.warn(_LW("ofport: %(ofport)s for VIF: %(vif)s is not a"
-                             " positive integer"),
-                         {'ofport': port['ofport'], 'vif': port_id})
-                continue
-            mac = port['external_ids'].get('attached-mac')
-            return VifPort(port['name'], port['ofport'], port_id, mac, self)
-        LOG.info(_LI("Port %(port_id)s not present in bridge %(br_name)s"),
-                 {'port_id': port_id, 'br_name': self.br_name})
-
-    def delete_ports(self, all_ports=False):
-        if all_ports:
-            port_names = self.get_port_name_list()
-        else:
-            port_names = (port.port_name for port in self.get_vif_ports())
-
-        for port_name in port_names:
-            self.delete_port(port_name)
-
-    def get_local_port_mac(self):
-        """Retrieve the mac of the bridge's local port."""
-        address = ip_lib.IPDevice(self.br_name).link.address
-        if address:
-            return address
-        else:
-            msg = _('Unable to determine mac address for %s') % self.br_name
-            raise Exception(msg)
-
-    def __enter__(self):
-        self.create()
-        return self
-
-    def __exit__(self, exc_type, exc_value, exc_tb):
-        self.destroy()
-
-
-class DeferredOVSBridge(object):
-    '''Deferred OVSBridge.
-
-    This class wraps add_flow, mod_flow and delete_flows calls to an OVSBridge
-    and defers their application until apply_flows call in order to perform
-    bulk calls. It wraps also ALLOWED_PASSTHROUGHS calls to avoid mixing
-    OVSBridge and DeferredOVSBridge uses.
-    This class can be used as a context, in such case apply_flows is called on
-    __exit__ except if an exception is raised.
-    This class is not thread-safe, that's why for every use a new instance
-    must be implemented.
-    '''
-    ALLOWED_PASSTHROUGHS = 'add_port', 'add_tunnel_port', 'delete_port'
-
-    def __init__(self, br, full_ordered=False,
-                 order=('add', 'mod', 'del')):
-        '''Constructor.
-
-        :param br: wrapped bridge
-        :param full_ordered: Optional, disable flow reordering (slower)
-        :param order: Optional, define in which order flow are applied
-        '''
-
-        self.br = br
-        self.full_ordered = full_ordered
-        self.order = order
-        if not self.full_ordered:
-            self.weights = dict((y, x) for x, y in enumerate(self.order))
-        self.action_flow_tuples = []
-
-    def __getattr__(self, name):
-        if name in self.ALLOWED_PASSTHROUGHS:
-            return getattr(self.br, name)
-        raise AttributeError(name)
-
-    def add_flow(self, **kwargs):
-        self.action_flow_tuples.append(('add', kwargs))
-
-    def mod_flow(self, **kwargs):
-        self.action_flow_tuples.append(('mod', kwargs))
-
-    def delete_flows(self, **kwargs):
-        self.action_flow_tuples.append(('del', kwargs))
-
-    def apply_flows(self):
-        action_flow_tuples = self.action_flow_tuples
-        self.action_flow_tuples = []
-        if not action_flow_tuples:
-            return
-
-        if not self.full_ordered:
-            action_flow_tuples.sort(key=lambda af: self.weights[af[0]])
-
-        grouped = itertools.groupby(action_flow_tuples,
-                                    key=operator.itemgetter(0))
-        itemgetter_1 = operator.itemgetter(1)
-        for action, action_flow_list in grouped:
-            flows = map(itemgetter_1, action_flow_list)
-            self.br.do_action_flows(action, flows)
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_value, traceback):
-        if exc_type is None:
-            self.apply_flows()
-        else:
-            LOG.exception(_LE("OVS flows could not be applied on bridge %s"),
-                          self.br.br_name)
-
-
-def _build_flow_expr_str(flow_dict, cmd):
-    flow_expr_arr = []
-    actions = None
-
-    if cmd == 'add':
-        flow_expr_arr.append("hard_timeout=%s" %
-                             flow_dict.pop('hard_timeout', '0'))
-        flow_expr_arr.append("idle_timeout=%s" %
-                             flow_dict.pop('idle_timeout', '0'))
-        flow_expr_arr.append("priority=%s" %
-                             flow_dict.pop('priority', '1'))
-    elif 'priority' in flow_dict:
-        msg = _("Cannot match priority on flow deletion or modification")
-        raise exceptions.InvalidInput(error_message=msg)
-
-    if cmd != 'del':
-        if "actions" not in flow_dict:
-            msg = _("Must specify one or more actions on flow addition"
-                    " or modification")
-            raise exceptions.InvalidInput(error_message=msg)
-        actions = "actions=%s" % flow_dict.pop('actions')
-
-    for key, value in flow_dict.iteritems():
-        if key == 'proto':
-            flow_expr_arr.append(value)
-        else:
-            flow_expr_arr.append("%s=%s" % (key, str(value)))
-
-    if actions:
-        flow_expr_arr.append(actions)
-
-    return ','.join(flow_expr_arr)
+INVALID_OFPORT = ovs_lib.INVALID_OFPORT
+BaseOVS = ovs_lib.BaseOVS
+OVSBridge = ovs_lib.OVSBridge
+VifPort = ovs_lib.VifPort
+_build_flow_expr_str = ovs_lib._build_flow_expr_str
index 49d9605e60864bce7ecb42963a389adec848b141..39a010cdaf5f9777a51675a9bb355b1a7272d404 100644 (file)
@@ -34,7 +34,7 @@ OPTS = [
 ]
 cfg.CONF.register_opts(OPTS, 'OVS')
 # TODO(twilson) DEFAULT.ovs_vsctl_timeout should be OVS.vsctl_timeout
-cfg.CONF.import_opt('ovs_vsctl_timeout', 'neutron.agent.linux.ovs_lib')
+cfg.CONF.import_opt('ovs_vsctl_timeout', 'neutron.agent.common.ovs_lib')
 
 LOG = logging.getLogger(__name__)
 
index 41ca1edd63b2440e4e43f3bf9243f45d398d8b6c..c2b74355f9da92a485194d917b4298a02f08c266 100644 (file)
@@ -21,6 +21,7 @@ from oslo_log import log as logging
 from oslo_utils import importutils
 
 from neutron.agent.common import config as agent_config
+from neutron.agent.common import ovs_lib
 from neutron.agent.dhcp import config as dhcp_config
 from neutron.agent.l3 import agent as l3_agent
 from neutron.agent.l3 import dvr
@@ -29,7 +30,6 @@ from neutron.agent.linux import dhcp
 from neutron.agent.linux import external_process
 from neutron.agent.linux import interface
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.api.v2 import attributes
 from neutron.common import config
 from neutron.i18n import _LE
index 180fae8ec6e83e0ae24c70dd96b95fb639b1d9b4..6a8a7e3b5556436c0d983c8c49635bd66e221b76 100644 (file)
@@ -17,10 +17,10 @@ from oslo_config import cfg
 from oslo_log import log as logging
 
 from neutron.agent.common import config as agent_config
+from neutron.agent.common import ovs_lib
 from neutron.agent.l3 import config as l3_config
 from neutron.agent.linux import interface
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.common import config
 from neutron.i18n import _LI
 
index 5519e16d10a248e3407324cb94f7248b29508b7d..aaeddbb1933a122d590db86a7e67f5682e587021 100644 (file)
@@ -19,9 +19,9 @@ import netaddr
 from oslo_log import log as logging
 import six
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import ip_lib
 from neutron.agent.linux import ip_link_support
-from neutron.agent.linux import ovs_lib
 from neutron.agent.linux import utils as agent_utils
 from neutron.common import utils
 from neutron.i18n import _LE
index f76a7ca76686506519987391c83597f22a5708dd..71c4a2a78752ee38f6d6adc8c8256a84602d8e7c 100644 (file)
@@ -26,8 +26,8 @@ from oslo_config import cfg
 from oslo_log import log as logging
 import oslo_messaging
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.agent import rpc as agent_rpc
 from neutron.common import config as common_config
 from neutron.common import constants as n_const
index 63dbae439a2ba1de6d6e87ee86acb5eae776918d..3ee3b7bf87a4b1f253d13e8fd2cb2f68a0afa9ab 100644 (file)
@@ -24,7 +24,7 @@ eventlet.monkey_patch()
 from oslo_log import log as logging
 import oslo_messaging
 
-from neutron.agent.linux import ovs_lib
+from neutron.agent.common import ovs_lib
 from neutron.agent import rpc as agent_rpc
 from neutron.agent import securitygroups_rpc as sg_rpc
 from neutron.common import config as common_config
index 5bacef11404ee9ad7a5e759085161082fe232bc8..9b8aabb725e3b9d1eaad4bcc1b2d0bc017001b09 100644 (file)
@@ -26,9 +26,9 @@ import oslo_messaging
 from six import moves
 
 from neutron.agent.common import config
+from neutron.agent.common import ovs_lib
 from neutron.agent import l2population_rpc
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.agent.linux import polling
 from neutron.agent.linux import utils
 from neutron.agent import rpc as agent_rpc
index 96e2e1b96f769a9aaf9e4be9f65faad79b89834e..de76385405c10e7784a9fed3e304c6f85a05e17f 100644 (file)
@@ -15,9 +15,9 @@
 import netaddr
 import testscenarios
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import bridge_lib
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.common import constants as n_const
 from neutron.tests.common import base
 from neutron.tests.common import net_helpers
old mode 100755 (executable)
new mode 100644 (file)
index 3dafa10..83d521e
@@ -26,6 +26,7 @@ import webob.dec
 import webob.exc
 
 from neutron.agent.common import config as agent_config
+from neutron.agent.common import ovs_lib
 from neutron.agent.l3 import agent as neutron_l3_agent
 from neutron.agent.l3 import dvr_snat_ns
 from neutron.agent.l3 import namespaces
@@ -33,7 +34,6 @@ from neutron.agent import l3_agent as l3_agent_main
 from neutron.agent.linux import dhcp
 from neutron.agent.linux import external_process
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.agent.linux import utils
 from neutron.common import config as common_config
 from neutron.common import constants as l3_constants
index 7c709b380be6cb1ff34b7d851dbfaa469573f42e..ad5b1700433d7208b6403b3fc6e63803310ffc86 100644 (file)
@@ -15,7 +15,7 @@
 
 import collections
 
-from neutron.agent.linux import ovs_lib
+from neutron.agent.common import ovs_lib
 from neutron.tests.common import net_helpers
 from neutron.tests.functional.agent.linux import base
 
similarity index 99%
rename from neutron/tests/unit/agent/linux/test_ovs_lib.py
rename to neutron/tests/unit/agent/common/test_ovs_lib.py
index 3924dbfcbaf51245c95cde6d8bdea81d63886a6e..0690bad54f50d53a9f223be085824ba9c088d694 100644 (file)
@@ -17,7 +17,7 @@ import mock
 from oslo_serialization import jsonutils
 import testtools
 
-from neutron.agent.linux import ovs_lib
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import utils
 from neutron.common import exceptions
 from neutron.openstack.common import uuidutils
index 309ba24149aac7d2da6e39084deea052ef92a54b..6cd2615e141e27bca1de323fdadf713f74f74ce7 100644 (file)
@@ -19,7 +19,7 @@ import mock
 from oslo_config import cfg
 import testtools
 
-from neutron.agent.linux import ovs_lib
+from neutron.agent.common import ovs_lib
 from neutron.agent import securitygroups_rpc as sg_rpc
 from neutron.common import topics
 from neutron.extensions import securitygroup as ext_sg
index 13d252114eb4f5b5c947749db2493e8884b818e0..35f54a4c8a848f8206864dc48ebc9c758b6ce48d 100644 (file)
@@ -60,16 +60,16 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
             mock.patch('neutron.plugins.openvswitch.agent.ovs_neutron_agent.'
                        'OVSNeutronAgent.setup_ancillary_bridges',
                        return_value=[]),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'create'),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'set_secure_mode'),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'get_local_port_mac',
                        return_value='00:00:00:00:00:01'),
             mock.patch('neutron.agent.linux.utils.get_interface_mac',
                        return_value='00:00:00:00:00:01'),
-            mock.patch('neutron.agent.linux.ovs_lib.BaseOVS.get_bridges'),
+            mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'),
             mock.patch('neutron.openstack.common.loopingcall.'
                        'FixedIntervalLoopingCall',
                        new=MockFixedIntervalLoopingCall)):
@@ -129,11 +129,11 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
         physical_network = self._physical_network
         segmentation_id = self._segmentation_id
         network_type = p_const.TYPE_VLAN
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                         'set_db_attribute',
                         return_value=True):
             with contextlib.nested(
-                mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+                mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                            'db_get_val',
                            return_value=self._old_local_vlan),
                 mock.patch.object(self.agent.dvr_agent.plugin_rpc,
@@ -249,11 +249,11 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
         self._compute_port.vif_mac = '77:88:99:00:11:22'
         physical_network = self._physical_network
         segmentation_id = self._segmentation_id
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                         'set_db_attribute',
                         return_value=True):
             with contextlib.nested(
-                mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+                mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                            'db_get_val',
                            return_value=self._old_local_vlan),
                 mock.patch.object(self.agent.dvr_agent.plugin_rpc,
@@ -381,11 +381,11 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
 
     def test_port_bound_for_dvr_with_csnat_ports(self, ofport=10):
         self._setup_for_dvr_test()
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                         'set_db_attribute',
                         return_value=True):
             with contextlib.nested(
-                mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+                mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                            'db_get_val',
                            return_value=self._old_local_vlan),
                 mock.patch.object(
@@ -429,11 +429,11 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
         else:
             gateway_ip = '2001:100::1'
             cidr = '2001:100::0/64'
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                         'set_db_attribute',
                         return_value=True):
             with contextlib.nested(
-                mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+                mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                            'db_get_val',
                            return_value=self._old_local_vlan),
                 mock.patch.object(
@@ -510,11 +510,11 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
         else:
             gateway_ip = '2001:100::1'
             cidr = '2001:100::0/64'
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                         'set_db_attribute',
                         return_value=True):
             with contextlib.nested(
-                mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+                mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                            'db_get_val',
                            return_value=self._old_local_vlan),
                 mock.patch.object(
@@ -587,11 +587,11 @@ class TestOvsDvrNeutronAgent(base.BaseTestCase):
 
     def test_treat_devices_removed_for_dvr_csnat_port(self, ofport=10):
         self._setup_for_dvr_test()
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                         'set_db_attribute',
                         return_value=True):
             with contextlib.nested(
-                mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+                mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                            'db_get_val',
                            return_value=self._old_local_vlan),
                 mock.patch.object(
index e2893a27e3fa50b8638a350e45def91fa10f48f9..1df71fe84a5b0d8c82d01bbca23f47788383a2cd 100644 (file)
@@ -22,9 +22,9 @@ from oslo_config import cfg
 from oslo_log import log
 import testtools
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import async_process
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.agent.linux import utils
 from neutron.common import constants as n_const
 from neutron.plugins.common import constants as p_const
@@ -115,16 +115,16 @@ class TestOvsNeutronAgent(base.BaseTestCase):
             mock.patch('neutron.plugins.openvswitch.agent.ovs_neutron_agent.'
                        'OVSNeutronAgent.setup_ancillary_bridges',
                        return_value=[]),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'create'),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'set_secure_mode'),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'get_local_port_mac',
                        return_value='00:00:00:00:00:01'),
             mock.patch('neutron.agent.linux.utils.get_interface_mac',
                        return_value='00:00:00:00:00:01'),
-            mock.patch('neutron.agent.linux.ovs_lib.BaseOVS.get_bridges'),
+            mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges'),
             mock.patch('neutron.openstack.common.loopingcall.'
                        'FixedIntervalLoopingCall',
                        new=MockFixedIntervalLoopingCall)):
@@ -147,9 +147,9 @@ class TestOvsNeutronAgent(base.BaseTestCase):
                 ovs_neutron_agent.LocalVLANMapping(
                     old_local_vlan, None, None, None))
         with contextlib.nested(
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'set_db_attribute', return_value=True),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'db_get_val', return_value=old_local_vlan),
             mock.patch.object(self.agent.int_br, 'delete_flows')
         ) as (set_ovs_db_func, get_ovs_db_func, delete_flows_func):
@@ -191,9 +191,9 @@ class TestOvsNeutronAgent(base.BaseTestCase):
         port = mock.Mock()
         port.ofport = 1
         with contextlib.nested(
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'set_db_attribute', return_value=True),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'db_get_val', return_value=cur_tag),
             mock.patch.object(self.agent.int_br, 'add_flow')
         ) as (set_ovs_db_func, get_ovs_db_func, add_flow_func):
@@ -1121,14 +1121,14 @@ class AncillaryBridgesTest(base.BaseTestCase):
                        'OVSNeutronAgent.setup_integration_br'),
             mock.patch('neutron.agent.linux.utils.get_interface_mac',
                        return_value='00:00:00:00:00:01'),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'get_local_port_mac',
                        return_value='00:00:00:00:00:01'),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge.'
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge.'
                        'set_secure_mode'),
-            mock.patch('neutron.agent.linux.ovs_lib.BaseOVS.get_bridges',
+            mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges',
                        return_value=bridges),
-            mock.patch('neutron.agent.linux.ovs_lib.BaseOVS.'
+            mock.patch('neutron.agent.common.ovs_lib.BaseOVS.'
                        'get_bridge_external_bridge_id',
                        side_effect=pullup_side_effect)):
             self.agent = ovs_neutron_agent.OVSNeutronAgent(**self.kwargs)
index c2fe7db5951385ca9a37c4acc9fd89283fe167ec..561ca80e95de11ba2fc438b0f51aedcf28601763 100644 (file)
@@ -21,8 +21,8 @@ import mock
 from oslo_config import cfg
 from oslo_log import log
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.plugins.common import constants as p_const
 from neutron.plugins.openvswitch.agent import ovs_neutron_agent
 from neutron.plugins.openvswitch.common import constants
index 29b64e8cd58eecf9f7123c2eeb2293254c735b8c..fd0d73f89575955c5c04baed139eb5a7f167a6d8 100644 (file)
@@ -16,9 +16,9 @@
 import mock
 
 from neutron.agent.common import config
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import interface
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.agent.linux import utils
 from neutron.common import constants
 from neutron.extensions import flavor
@@ -273,7 +273,7 @@ class TestOVSInterfaceDriver(TestBase):
     def test_unplug(self, bridge=None):
         if not bridge:
             bridge = 'br-int'
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge') as ovs_br:
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge') as ovs_br:
             ovs = interface.OVSInterfaceDriver(self.conf)
             ovs.unplug('tap0')
             ovs_br.assert_has_calls([mock.call(bridge),
@@ -347,7 +347,7 @@ class TestOVSInterfaceDriverWithVeth(TestOVSInterfaceDriver):
     def test_unplug(self, bridge=None):
         if not bridge:
             bridge = 'br-int'
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge') as ovs_br:
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge') as ovs_br:
             ovs = interface.OVSInterfaceDriver(self.conf)
             ovs.unplug('ns-0', bridge=bridge)
             ovs_br.assert_has_calls([mock.call(bridge),
index 9b28fac04efcf665a5edd8db4e59c56fb5df9355..2da02c77f74b7b50b85acc390d6ab9263123f2de 100644 (file)
@@ -96,9 +96,10 @@ class TestNetnsCleanup(base.BaseTestCase):
         device.name = 'tap1'
         device.link.delete.side_effect = RuntimeError
 
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge') as ovs_br_cls:
+        with mock.patch(
+                'neutron.agent.common.ovs_lib.OVSBridge') as ovs_br_cls:
             br_patch = mock.patch(
-                'neutron.agent.linux.ovs_lib.BaseOVS.get_bridge_for_iface')
+                'neutron.agent.common.ovs_lib.BaseOVS.get_bridge_for_iface')
             with br_patch as mock_get_bridge_for_iface:
                 mock_get_bridge_for_iface.return_value = 'br-int'
                 ovs_bridge = mock.Mock()
@@ -119,9 +120,10 @@ class TestNetnsCleanup(base.BaseTestCase):
         device.name = 'tap1'
         device.link.delete.side_effect = RuntimeError
 
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge') as ovs_br_cls:
+        with mock.patch(
+                'neutron.agent.common.ovs_lib.OVSBridge') as ovs_br_cls:
             br_patch = mock.patch(
-                'neutron.agent.linux.ovs_lib.BaseOVS.get_bridge_for_iface')
+                'neutron.agent.common.ovs_lib.BaseOVS.get_bridge_for_iface')
             with br_patch as mock_get_bridge_for_iface:
                 with mock.patch.object(util.LOG, 'debug') as debug:
                     mock_get_bridge_for_iface.return_value = None
index 591f9204ccd82de0cfe22d9631d89a31e86fc171..6e650dd28aad19f5a9099529a3e305e20afd83e5 100644 (file)
@@ -17,8 +17,8 @@ import contextlib
 import itertools
 import mock
 
+from neutron.agent.common import ovs_lib
 from neutron.agent.linux import ip_lib
-from neutron.agent.linux import ovs_lib
 from neutron.cmd import ovs_cleanup as util
 from neutron.openstack.common import uuidutils
 from neutron.tests import base
@@ -37,9 +37,9 @@ class TestOVSCleanup(base.BaseTestCase):
             mock.patch('neutron.common.config.setup_logging'),
             mock.patch('neutron.cmd.ovs_cleanup.setup_conf',
                        return_value=conf),
-            mock.patch('neutron.agent.linux.ovs_lib.BaseOVS.get_bridges',
+            mock.patch('neutron.agent.common.ovs_lib.BaseOVS.get_bridges',
                        return_value=bridges),
-            mock.patch('neutron.agent.linux.ovs_lib.OVSBridge'),
+            mock.patch('neutron.agent.common.ovs_lib.OVSBridge'),
             mock.patch.object(util, 'collect_neutron_ports',
                               return_value=ports),
             mock.patch.object(util, 'delete_neutron_ports')
@@ -60,7 +60,7 @@ class TestOVSCleanup(base.BaseTestCase):
                                 '99:00:aa:bb:cc:dd', 'br')
         ports = [[port1, port2], [port3]]
         portnames = [p.port_name for p in itertools.chain(*ports)]
-        with mock.patch('neutron.agent.linux.ovs_lib.OVSBridge') as ovs:
+        with mock.patch('neutron.agent.common.ovs_lib.OVSBridge') as ovs:
             ovs.return_value.get_vif_ports.side_effect = ports
             bridges = ['br-int', 'br-ex']
             ret = util.collect_neutron_ports(bridges)