Backport Neutron port data plane status
[apex.git] / build / patches / neutron-patch-NSDriver.patch
1 From ff4e918d21970a81604a0aaa2af888141f93cdac Mon Sep 17 00:00:00 2001
2 From: Feng Pan <fpan@redhat.com>
3 Date: Sun, 5 Feb 2017 21:34:19 -0500
4 Subject: [PATCH] Add NSDriver
5
6 ---
7  neutron/agent/l3/namespaces.py   |  6 ++--
8  neutron/agent/l3/router_info.py  | 14 ++++----
9  neutron/agent/linux/interface.py | 76 +++++++++++++++++++++++++++++++++++++++-
10  3 files changed, 87 insertions(+), 9 deletions(-)
11
12 diff --git a/neutron/agent/l3/namespaces.py b/neutron/agent/l3/namespaces.py
13 index e70d7bb..3c932a8 100644
14 --- a/neutron/agent/l3/namespaces.py
15 +++ b/neutron/agent/l3/namespaces.py
16 @@ -18,6 +18,7 @@ import functools
17  from oslo_log import log as logging
18  from oslo_utils import excutils
19  
20 +from neutron.agent.linux.interface import OVSInterfaceDriver
21  from neutron._i18n import _LE, _LW
22  from neutron.agent.linux import ip_lib
23  
24 @@ -110,8 +111,9 @@ class Namespace(object):
25  
26  class RouterNamespace(Namespace):
27  
28 -    def __init__(self, router_id, agent_conf, driver, use_ipv6):
29 +    def __init__(self, router_id, agent_conf, driver, use_ipv6, ovs_driver):
30          self.router_id = router_id
31 +        self.ovs_driver = ovs_driver
32          name = self._get_ns_name(router_id)
33          super(RouterNamespace, self).__init__(
34              name, agent_conf, driver, use_ipv6)
35 @@ -131,7 +133,7 @@ class RouterNamespace(Namespace):
36              elif d.name.startswith(ROUTER_2_FIP_DEV_PREFIX):
37                  ns_ip.del_veth(d.name)
38              elif d.name.startswith(EXTERNAL_DEV_PREFIX):
39 -                self.driver.unplug(
40 +                self.ovs_driver.unplug(
41                      d.name,
42                      bridge=self.agent_conf.external_network_bridge,
43                      namespace=self.name,
44 diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py
45 index 3fd3934..b33fb7e 100644
46 --- a/neutron/agent/l3/router_info.py
47 +++ b/neutron/agent/l3/router_info.py
48 @@ -27,6 +27,7 @@ from neutron.common import exceptions as n_exc
49  from neutron.common import ipv6_utils
50  from neutron.common import utils as common_utils
51  from neutron.ipam import utils as ipam_utils
52 +from neutron.agent.linux.interface import OVSInterfaceDriver
53  
54  LOG = logging.getLogger(__name__)
55  INTERNAL_DEV_PREFIX = namespaces.INTERNAL_DEV_PREFIX
56 @@ -47,6 +48,7 @@ class RouterInfo(object):
57                   agent_conf,
58                   interface_driver,
59                   use_ipv6=False):
60 +        self.ovs_driver = OVSInterfaceDriver(agent_conf)
61          self.router_id = router_id
62          self.ex_gw_port = None
63          self._snat_enabled = None
64 @@ -57,7 +59,7 @@ class RouterInfo(object):
65          self.router = router
66          self.use_ipv6 = use_ipv6
67          ns = self.create_router_namespace_object(
68 -            router_id, agent_conf, interface_driver, use_ipv6)
69 +            router_id, agent_conf, interface_driver, use_ipv6, self.ovs_driver)
70          self.router_namespace = ns
71          self.ns_name = ns.name
72          self.available_mark_ids = set(range(ADDRESS_SCOPE_MARK_ID_MIN,
73 @@ -94,9 +96,9 @@ class RouterInfo(object):
74          self.router_namespace.create()
75  
76      def create_router_namespace_object(
77 -            self, router_id, agent_conf, iface_driver, use_ipv6):
78 +            self, router_id, agent_conf, iface_driver, use_ipv6, ovs_driver):
79          return namespaces.RouterNamespace(
80 -            router_id, agent_conf, iface_driver, use_ipv6)
81 +            router_id, agent_conf, iface_driver, use_ipv6, ovs_driver)
82  
83      @property
84      def router(self):
85 @@ -583,7 +585,7 @@ class RouterInfo(object):
86                  for ip in floating_ips]
87  
88      def _plug_external_gateway(self, ex_gw_port, interface_name, ns_name):
89 -        self.driver.plug(ex_gw_port['network_id'],
90 +        self.ovs_driver.plug(ex_gw_port['network_id'],
91                           ex_gw_port['id'],
92                           interface_name,
93                           ex_gw_port['mac_address'],
94 @@ -641,7 +643,7 @@ class RouterInfo(object):
95  
96          self._add_route_to_gw(ex_gw_port, device_name=interface_name,
97                                namespace=ns_name, preserve_ips=preserve_ips)
98 -        self.driver.init_router_port(
99 +        self.ovs_driver.init_router_port(
100              interface_name,
101              ip_cidrs,
102              namespace=ns_name,
103 @@ -735,7 +737,7 @@ class RouterInfo(object):
104          for stale_dev in stale_devs:
105              LOG.debug('Deleting stale external router device: %s', stale_dev)
106              pd.remove_gw_interface(self.router['id'])
107 -            self.driver.unplug(stale_dev,
108 +            self.ovs_driver.unplug(stale_dev,
109                                 bridge=self.agent_conf.external_network_bridge,
110                                 namespace=self.ns_name,
111                                 prefix=EXTERNAL_DEV_PREFIX)
112 diff --git a/neutron/agent/linux/interface.py b/neutron/agent/linux/interface.py
113 index c2eb06e..80da16f 100644
114 --- a/neutron/agent/linux/interface.py
115 +++ b/neutron/agent/linux/interface.py
116 @@ -15,7 +15,7 @@
117  
118  import abc
119  import time
120 -
121 +import eventlet
122  import netaddr
123  from neutron_lib import constants
124  from oslo_config import cfg
125 @@ -288,6 +288,80 @@ class NullDriver(LinuxInterfaceDriver):
126      def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
127          pass
128  
129 +class NSDriver(LinuxInterfaceDriver):
130 +    """Device independent driver enabling creation of a non device specific
131 +    interface in network spaces.  Attachment to the device is not performed.
132 +    """
133 +    MAX_TIME_FOR_DEVICE_EXISTENCE = 30
134 +
135 +    @classmethod
136 +    def _device_is_created_in_time(cls, device_name):
137 +        """See if device is created, within time limit."""
138 +        attempt = 0
139 +        while attempt < NSDriver.MAX_TIME_FOR_DEVICE_EXISTENCE:
140 +            if ip_lib.device_exists(device_name):
141 +                return True
142 +            attempt += 1
143 +            eventlet.sleep(1)
144 +        LOG.error(_LE("Device %(dev)s was not created in %(time)d seconds"),
145 +                  {'dev': device_name,
146 +                   'time': NSDriver.MAX_TIME_FOR_DEVICE_EXISTENCE})
147 +        return False
148 +
149 +    def _configure_mtu(self, ns_dev, mtu=None):
150 +        # Need to set MTU, after added to namespace. See review
151 +        # https://review.openstack.org/327651
152 +        try:
153 +            # Note: network_device_mtu will be deprecated in future
154 +            mtu_override = self.conf.network_device_mtu
155 +        except cfg.NoSuchOptError:
156 +            LOG.warning(_LW("Config setting for MTU deprecated - any "
157 +                            "override will be ignored."))
158 +            mtu_override = None
159 +        if mtu_override:
160 +            mtu = mtu_override
161 +            LOG.debug("Overriding MTU to %d", mtu)
162 +        if mtu:
163 +            ns_dev.link.set_mtu(mtu)
164 +        else:
165 +            LOG.debug("No MTU provided - skipping setting value")
166 +
167 +    def plug(self, network_id, port_id, device_name, mac_address,
168 +             bridge=None, namespace=None, prefix=None, mtu=None):
169 +
170 +        # Overriding this, we still want to add an existing device into the
171 +        # namespace.
172 +        self.plug_new(network_id, port_id, device_name, mac_address,
173 +                      bridge, namespace, prefix, mtu)
174 +
175 +    def plug_new(self, network_id, port_id, device_name, mac_address,
176 +                 bridge=None, namespace=None, prefix=None, mtu=None):
177 +
178 +        ip = ip_lib.IPWrapper()
179 +        ns_dev = ip.device(device_name)
180 +
181 +        LOG.debug("Plugging dev: '%s' into namespace: '%s' ",
182 +                  device_name, namespace)
183 +
184 +        # Wait for device creation
185 +        if not self._device_is_created_in_time(device_name):
186 +            return
187 +
188 +        ns_dev.link.set_address(mac_address)
189 +
190 +        if namespace:
191 +            namespace_obj = ip.ensure_namespace(namespace)
192 +            namespace_obj.add_device_to_namespace(ns_dev)
193 +
194 +        self._configure_mtu(ns_dev, mtu)
195 +
196 +        ns_dev.link.set_up()
197 +
198 +    def unplug(self, device_name, bridge=None, namespace=None, prefix=None):
199 +        # Device removal is done externally. Just remove the namespace
200 +        LOG.debug("Removing namespace: '%s'", namespace)
201 +        ip_lib.IPWrapper(namespace).garbage_collect_namespace()
202 +
203  
204  class OVSInterfaceDriver(LinuxInterfaceDriver):
205      """Driver for creating an internal interface on an OVS bridge."""
206 diff --git a/neutron/agent/l3/ha_router.py b/usr/lib/python2.7/site-packages/neutron/agent/l3/ha_router.py
207 index ca0e50d..2c4fdad 100644
208 --- a/neutron/agent/l3/ha_router.py
209 +++ b/usr/lib/python2.7/site-packages/neutron/agent/l3/ha_router.py
210 @@ -52,15 +52,14 @@ class HaRouterNamespace(namespaces.RouterNamespace):
211  class HaRouter(router.RouterInfo):
212      def __init__(self, state_change_callback, *args, **kwargs):
213          super(HaRouter, self).__init__(*args, **kwargs)
214 -
215          self.ha_port = None
216          self.keepalived_manager = None
217          self.state_change_callback = state_change_callback
218  
219      def create_router_namespace_object(
220 -            self, router_id, agent_conf, iface_driver, use_ipv6):
221 +            self, router_id, agent_conf, iface_driver, use_ipv6, ovs_driver):
222          return HaRouterNamespace(
223 -            router_id, agent_conf, iface_driver, use_ipv6)
224 +            router_id, agent_conf, iface_driver, use_ipv6, ovs_driver)
225  
226      @property
227      def ha_priority(self):
228
229 -- 
230 2.9.3
231