aboutsummaryrefslogtreecommitdiffstats
path: root/LICENSE
blob: f4346f82c46562f01eb5b9eccb7f8eb0ad8aee47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
Copyright 2015 Open Platform for NFV Project, Inc. and its contributors

   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.
>206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
From ff4e918d21970a81604a0aaa2af888141f93cdac Mon Sep 17 00:00:00 2001
From: Feng Pan <fpan@redhat.com>
Date: Sun, 5 Feb 2017 21:34:19 -0500
Subject: [PATCH] Add NSDriver

---
 neutron/agent/l3/namespaces.py   |  6 ++--
 neutron/agent/l3/router_info.py  | 14 ++++----
 neutron/agent/linux/interface.py | 76 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 87 insertions(+), 9 deletions(-)

diff --git a/neutron/agent/l3/namespaces.py b/neutron/agent/l3/namespaces.py
index e70d7bb..3c932a8 100644
--- a/neutron/agent/l3/namespaces.py
+++ b/neutron/agent/l3/namespaces.py
@@ -18,6 +18,7 @@ import functools
 from oslo_log import log as logging
 from oslo_utils import excutils
 
+from neutron.agent.linux.interface import OVSInterfaceDriver
 from neutron._i18n import _LE, _LW
 from neutron.agent.linux import ip_lib
 
@@ -110,8 +111,9 @@ class Namespace(object):
 
 class RouterNamespace(Namespace):
 
-    def __init__(self, router_id, agent_conf, driver, use_ipv6):
+    def __init__(self, router_id, agent_conf, driver, use_ipv6, ovs_driver):
         self.router_id = router_id
+        self.ovs_driver = ovs_driver
         name = self._get_ns_name(router_id)
         super(RouterNamespace, self).__init__(
             name, agent_conf, driver, use_ipv6)
@@ -131,7 +133,7 @@ class RouterNamespace(Namespace):
             elif d.name.startswith(ROUTER_2_FIP_DEV_PREFIX):
                 ns_ip.del_veth(d.name)
             elif d.name.startswith(EXTERNAL_DEV_PREFIX):
-                self.driver.unplug(
+                self.ovs_driver.unplug(
                     d.name,
                     bridge=self.agent_conf.external_network_bridge,
                     namespace=self.name,
diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py
index 3fd3934..b33fb7e 100644
--- a/neutron/agent/l3/router_info.py
+++ b/neutron/agent/l3/router_info.py
@@ -27,6 +27,7 @@ from neutron.common import exceptions as n_exc
 from neutron.common import ipv6_utils
 from neutron.common import utils as common_utils
 from neutron.ipam import utils as ipam_utils
+from neutron.agent.linux.interface import OVSInterfaceDriver
 
 LOG = logging.getLogger(__name__)
 INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX
@@ -47,6 +48,7 @@ class RouterInfo(object):
                  agent_conf,
                  interface_driver,
                  use_ipv6=False):
+        self.ovs_driver = OVSInterfaceDriver(agent_conf)
         self.router_id = router_id
         self.ex_gw_port = None
         self._snat_enabled = None
@@ -57,7 +59,7 @@ class RouterInfo(object):
         self.router = router
         self.use_ipv6 = use_ipv6
         ns = self.create_router_namespace_object(
-            router_id, agent_conf, interface_driver, use_ipv6)
+            router_id, agent_conf, interface_driver, use_ipv6, self.ovs_driver)
         self.router_namespace = ns
         self.ns_name = ns.name
         self.available_mark_ids = set(range(ADDRESS_SCOPE_MARK_ID_MIN,
@@ -94,9 +96,9 @@ class RouterInfo(object):
         self.router_namespace.create()
 
     def create_router_namespace_object(
-            self, router_id, agent_conf, iface_driver, use_ipv6):
+            self, router_id, agent_conf, iface_driver, use_ipv6, ovs_driver):
         return namespaces.RouterNamespace(
-            router_id, agent_conf, iface_driver, use_ipv6)
+            router_id, agent_conf, iface_driver, use_ipv6, ovs_driver)
 
     @property
     def router(self):
@@ -583,7 +585,7 @@ class RouterInfo(object):
                 for ip in floating_ips]
 
     def _plug_external_gateway(self, ex_gw_port, interface_name, ns_name):
-        self.driver.plug(ex_gw_port['network_id'],
+        self.ovs_driver.plug(ex_gw_port['network_id'],
                          ex_gw_port['id'],
                          interface_name,
                          ex_gw_port['mac_address'],
@@ -641,7 +643,7 @@ class RouterInfo(object):
 
         self._add_route_to_gw(ex_gw_port, device_name=interface_name,
                               namespace=ns_name, preserve_ips=preserve_ips)
-        self.driver.init_router_port(
+        self.ovs_driver.init_router_port(
             interface_name,
             ip_cidrs,
             namespace=ns_name,
@@ -735,7 +737,7 @@ class RouterInfo(object):
         for stale_dev in stale_devs:
             LOG.debug('Deleting stale external router device: %s', stale_dev)
             pd.remove_gw_interface(self.router['id'])
-            self.driver.unplug(stale_dev,
+            self.ovs_driver.unplug(stale_dev,
                                bridge=self.agent_conf.external_network_bridge,
                                namespace=self.ns_name,
                                prefix=EXTERNAL_DEV_PREFIX)
diff --git a/neutron/agent/linux/interface.py b/neutron/agent/linux/interface.py
index c2eb06e..80da16f 100644
--- a/neutron/agent/linux/interface.py
+++ b/neutron/agent/linux/interface.py
@@ -15,7 +15,7 @@
 
 import abc
 import time
-
+import eventlet
 import netaddr
 from neutron_lib import constants
 from oslo_config import cfg
@@ -288,6 +288,80 @@ class NullDriver(LinuxInterfaceDriver):
     def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
         pass
 
+class NSDriver(LinuxInterfaceDriver):
+    """Device independent driver enabling creation of a non device specific
+    interface in network spaces.  Attachment to the device is not performed.
+    """
+    MAX_TIME_FOR_DEVICE_EXISTENCE = 30
+
+    @classmethod
+    def _device_is_created_in_time(cls, device_name):
+        """See if device is created, within time limit."""
+        attempt = 0
+        while attempt < NSDriver.MAX_TIME_FOR_DEVICE_EXISTENCE:
+            if ip_lib.device_exists(device_name):
+                return True
+            attempt += 1
+            eventlet.sleep(1)
+        LOG.error(_LE("Device %(dev)s was not created in %(time)d seconds"),
+                  {'dev': device_name,
+                   'time': NSDriver.MAX_TIME_FOR_DEVICE_EXISTENCE})
+        return False
+
+    def _configure_mtu(self, ns_dev, mtu=None):
+        # Need to set MTU, after added to namespace. See review
+        # https://review.openstack.org/327651
+        try:
+            # Note: network_device_mtu will be deprecated in future
+            mtu_override = self.conf.network_device_mtu
+        except cfg.NoSuchOptError:
+            LOG.warning(_LW("Config setting for MTU deprecated - any "
+                            "override will be ignored."))
+            mtu_override = None
+        if mtu_override:
+            mtu = mtu_override
+            LOG.debug("Overriding MTU to %d", mtu)
+        if mtu:
+            ns_dev.link.set_mtu(mtu)
+        else:
+            LOG.debug("No MTU provided - skipping setting value")
+
+    def plug(self, network_id, port_id, device_name, mac_address,
+             bridge=None, namespace=None, prefix=None, mtu=None):
+
+        # Overriding this, we still want to add an existing device into the
+        # namespace.
+        self.plug_new(network_id, port_id, device_name, mac_address,
+                      bridge, namespace, prefix, mtu)
+
+    def plug_new(self, network_id, port_id, device_name, mac_address,
+                 bridge=None, namespace=None, prefix=None, mtu=None):
+
+        ip = ip_lib.IPWrapper()
+        ns_dev = ip.device(device_name)
+
+        LOG.debug("Plugging dev: '%s' into namespace: '%s' ",
+                  device_name, namespace)
+
+        # Wait for device creation
+        if not self._device_is_created_in_time(device_name):
+            return
+
+        ns_dev.link.set_address(mac_address)
+
+        if namespace:
+            namespace_obj = ip.ensure_namespace(namespace)
+            namespace_obj.add_device_to_namespace(ns_dev)
+
+        self._configure_mtu(ns_dev, mtu)
+
+        ns_dev.link.set_up()
+
+    def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
+        # Device removal is done externally. Just remove the namespace
+        LOG.debug("Removing namespace: '%s'", namespace)
+        ip_lib.IPWrapper(namespace).garbage_collect_namespace()
+
 
 class OVSInterfaceDriver(LinuxInterfaceDriver):
     """Driver for creating an internal interface on an OVS bridge."""
diff --git a/neutron/agent/l3/ha_router.py b/usr/lib/python2.7/site-packages/neutron/agent/l3/ha_router.py
index ca0e50d..2c4fdad 100644
--- a/neutron/agent/l3/ha_router.py
+++ b/usr/lib/python2.7/site-packages/neutron/agent/l3/ha_router.py
@@ -52,15 +52,14 @@ class HaRouterNamespace(namespaces.RouterNamespace):
 class HaRouter(router.RouterInfo):
     def __init__(self, state_change_callback, *args, **kwargs):
         super(HaRouter, self).__init__(*args, **kwargs)
-
         self.ha_port = None
         self.keepalived_manager = None
         self.state_change_callback = state_change_callback
 
     def create_router_namespace_object(
-            self, router_id, agent_conf, iface_driver, use_ipv6):
+            self, router_id, agent_conf, iface_driver, use_ipv6, ovs_driver):
         return HaRouterNamespace(
-            router_id, agent_conf, iface_driver, use_ipv6)
+            router_id, agent_conf, iface_driver, use_ipv6, ovs_driver)
 
     @property
     def ha_priority(self):

-- 
2.9.3