|
1 In-house patch to the Neutron L3 agent to allow an alternate implementation (in |
|
2 this case, EVS) of L3 and NAT support. This patch has not yet been |
|
3 submitted upstream. |
|
4 |
|
5 --- quantum-2013.1.4/quantum/agent/l3_agent.py.~1~ 2013-10-17 11:24:18.000000000 -0700 |
|
6 +++ quantum-2013.1.4/quantum/agent/l3_agent.py 2014-03-13 01:51:36.761165189 -0700 |
|
7 @@ -3,6 +3,8 @@ |
|
8 # |
|
9 # Copyright 2012 Nicira Networks, Inc. All rights reserved. |
|
10 # |
|
11 +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. |
|
12 +# |
|
13 # Licensed under the Apache License, Version 2.0 (the "License"); you may |
|
14 # not use this file except in compliance with the License. You may obtain |
|
15 # a copy of the License at |
|
16 @@ -16,12 +18,14 @@ |
|
17 # under the License. |
|
18 # |
|
19 # @author: Dan Wendlandt, Nicira, Inc |
|
20 +# @author: Girish Moodalbail, Oracle, Inc |
|
21 # |
|
22 """ |
|
23 |
|
24 import eventlet |
|
25 from eventlet import semaphore |
|
26 import netaddr |
|
27 +import platform |
|
28 from oslo.config import cfg |
|
29 |
|
30 from quantum.agent.common import config |
|
31 @@ -31,6 +35,8 @@ |
|
32 from quantum.agent.linux import iptables_manager |
|
33 from quantum.agent.linux import utils |
|
34 from quantum.agent import rpc as agent_rpc |
|
35 +from quantum.agent.solaris import ipfilters_manager |
|
36 +from quantum.agent.solaris import net_lib |
|
37 from quantum.common import constants as l3_constants |
|
38 from quantum.common import topics |
|
39 from quantum.common import utils as common_utils |
|
40 @@ -113,6 +119,8 @@ |
|
41 |
|
42 class L3NATAgent(manager.Manager): |
|
43 |
|
44 + RouterInfo = RouterInfo |
|
45 + |
|
46 OPTS = [ |
|
47 cfg.StrOpt('external_network_bridge', default='br-ex', |
|
48 help=_("Name of bridge used for external network " |
|
49 @@ -223,8 +231,8 @@ |
|
50 raise |
|
51 |
|
52 def _router_added(self, router_id, router): |
|
53 - ri = RouterInfo(router_id, self.root_helper, |
|
54 - self.conf.use_namespaces, router) |
|
55 + ri = self.RouterInfo(router_id, self.root_helper, |
|
56 + self.conf.use_namespaces, router) |
|
57 self.router_info[router_id] = ri |
|
58 if self.conf.use_namespaces: |
|
59 self._create_router_namespace(ri) |
|
60 @@ -303,14 +311,11 @@ |
|
61 for p in new_ports: |
|
62 self._set_subnet_info(p) |
|
63 ri.internal_ports.append(p) |
|
64 - self.internal_network_added(ri, ex_gw_port, |
|
65 - p['network_id'], p['id'], |
|
66 - p['ip_cidr'], p['mac_address']) |
|
67 + self.internal_network_added(ri, ex_gw_port, p) |
|
68 |
|
69 for p in old_ports: |
|
70 ri.internal_ports.remove(p) |
|
71 - self.internal_network_removed(ri, ex_gw_port, p['id'], |
|
72 - p['ip_cidr']) |
|
73 + self.internal_network_removed(ri, ex_gw_port, p) |
|
74 |
|
75 internal_cidrs = [p['ip_cidr'] for p in ri.internal_ports] |
|
76 |
|
77 @@ -470,16 +475,17 @@ |
|
78 rules.extend(self.internal_network_nat_rules(ex_gw_ip, cidr)) |
|
79 return rules |
|
80 |
|
81 - def internal_network_added(self, ri, ex_gw_port, network_id, port_id, |
|
82 - internal_cidr, mac_address): |
|
83 - interface_name = self.get_internal_device_name(port_id) |
|
84 + def internal_network_added(self, ri, ex_gw_port, p): |
|
85 + |
|
86 + interface_name = self.get_internal_device_name(p['id']) |
|
87 if not ip_lib.device_exists(interface_name, |
|
88 root_helper=self.root_helper, |
|
89 namespace=ri.ns_name()): |
|
90 - self.driver.plug(network_id, port_id, interface_name, mac_address, |
|
91 + self.driver.plug(p['network_id'], p['id'], interface_name, |
|
92 + p['mac_address'], |
|
93 namespace=ri.ns_name(), |
|
94 prefix=INTERNAL_DEV_PREFIX) |
|
95 - |
|
96 + internal_cidr = p['ip_cidr'] |
|
97 self.driver.init_l3(interface_name, [internal_cidr], |
|
98 namespace=ri.ns_name()) |
|
99 ip_address = internal_cidr.split('/')[0] |
|
100 @@ -492,8 +498,8 @@ |
|
101 ri.iptables_manager.ipv4['nat'].add_rule(c, r) |
|
102 ri.iptables_manager.apply() |
|
103 |
|
104 - def internal_network_removed(self, ri, ex_gw_port, port_id, internal_cidr): |
|
105 - interface_name = self.get_internal_device_name(port_id) |
|
106 + def internal_network_removed(self, ri, ex_gw_port, p): |
|
107 + interface_name = self.get_internal_device_name(p['id']) |
|
108 if ip_lib.device_exists(interface_name, |
|
109 root_helper=self.root_helper, |
|
110 namespace=ri.ns_name()): |
|
111 @@ -503,7 +509,7 @@ |
|
112 if ex_gw_port: |
|
113 ex_gw_ip = ex_gw_port['fixed_ips'][0]['ip_address'] |
|
114 for c, r in self.internal_network_nat_rules(ex_gw_ip, |
|
115 - internal_cidr): |
|
116 + p['ip_cidr']): |
|
117 ri.iptables_manager.ipv4['nat'].remove_rule(c, r) |
|
118 ri.iptables_manager.apply() |
|
119 |
|
120 @@ -742,16 +748,20 @@ |
|
121 def main(): |
|
122 eventlet.monkey_patch() |
|
123 conf = cfg.CONF |
|
124 - conf.register_opts(L3NATAgent.OPTS) |
|
125 config.register_agent_state_opts_helper(conf) |
|
126 config.register_root_helper(conf) |
|
127 conf.register_opts(interface.OPTS) |
|
128 conf.register_opts(external_process.OPTS) |
|
129 + if platform.system() == "SunOS": |
|
130 + manager = 'quantum.agent.evs_l3_agent.EVSL3NATAgent' |
|
131 + else: |
|
132 + conf.register_opts(L3NATAgent.OPTS) |
|
133 + manager = 'quantum.agent.l3_agent.L3NATAgentWithStateReport' |
|
134 conf(project='quantum') |
|
135 config.setup_logging(conf) |
|
136 server = quantum_service.Service.create( |
|
137 binary='quantum-l3-agent', |
|
138 topic=topics.L3_AGENT, |
|
139 report_interval=cfg.CONF.AGENT.report_interval, |
|
140 - manager='quantum.agent.l3_agent.L3NATAgentWithStateReport') |
|
141 + manager=manager) |
|
142 service.launch(server).wait() |
|
143 --- quantum-2013.1.4/quantum/db/l3_db.py.~1~ 2013-10-17 11:24:18.000000000 -0700 |
|
144 +++ quantum-2013.1.4/quantum/db/l3_db.py 2014-03-13 01:48:03.082634902 -0700 |
|
145 @@ -2,6 +2,8 @@ |
|
146 |
|
147 # Copyright 2012 Nicira Networks, Inc. All rights reserved. |
|
148 # |
|
149 +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. |
|
150 +# |
|
151 # Licensed under the Apache License, Version 2.0 (the "License"); you may |
|
152 # not use this file except in compliance with the License. You may obtain |
|
153 # a copy of the License at |
|
154 @@ -15,6 +17,7 @@ |
|
155 # under the License. |
|
156 # |
|
157 # @author: Dan Wendlandt, Nicira, Inc |
|
158 +# @author: Girish Moodalbail, Oracle, Inc |
|
159 # |
|
160 |
|
161 import netaddr |
|
162 @@ -82,6 +85,9 @@ |
|
163 class L3_NAT_db_mixin(l3.RouterPluginBase): |
|
164 """Mixin class to add L3/NAT router methods to db_plugin_base_v2""" |
|
165 |
|
166 + Router = Router |
|
167 + FloatingIP = FloatingIP |
|
168 + |
|
169 def _network_model_hook(self, context, original_model, query): |
|
170 query = query.outerjoin(ExternalNetwork, |
|
171 (original_model.id == |
|
172 @@ -117,7 +123,7 @@ |
|
173 |
|
174 def _get_router(self, context, id): |
|
175 try: |
|
176 - router = self._get_by_id(context, Router, id) |
|
177 + router = self._get_by_id(context, self.Router, id) |
|
178 except exc.NoResultFound: |
|
179 raise l3.RouterNotFound(router_id=id) |
|
180 except exc.MultipleResultsFound: |
|
181 @@ -148,11 +154,11 @@ |
|
182 with context.session.begin(subtransactions=True): |
|
183 # pre-generate id so it will be available when |
|
184 # configuring external gw port |
|
185 - router_db = Router(id=uuidutils.generate_uuid(), |
|
186 - tenant_id=tenant_id, |
|
187 - name=r['name'], |
|
188 - admin_state_up=r['admin_state_up'], |
|
189 - status="ACTIVE") |
|
190 + router_db = self.Router(id=uuidutils.generate_uuid(), |
|
191 + tenant_id=tenant_id, |
|
192 + name=r['name'], |
|
193 + admin_state_up=r['admin_state_up'], |
|
194 + status="ACTIVE") |
|
195 context.session.add(router_db) |
|
196 if has_gw_info: |
|
197 self._update_router_gw_info(context, router_db['id'], gw_info) |
|
198 @@ -273,7 +279,7 @@ |
|
199 sorts=None, limit=None, marker=None, |
|
200 page_reverse=False): |
|
201 marker_obj = self._get_marker_obj(context, 'router', limit, marker) |
|
202 - return self._get_collection(context, Router, |
|
203 + return self._get_collection(context, self.Router, |
|
204 self._make_router_dict, |
|
205 filters=filters, fields=fields, |
|
206 sorts=sorts, |
|
207 @@ -282,15 +288,14 @@ |
|
208 page_reverse=page_reverse) |
|
209 |
|
210 def get_routers_count(self, context, filters=None): |
|
211 - return self._get_collection_count(context, Router, |
|
212 + return self._get_collection_count(context, self.Router, |
|
213 filters=filters) |
|
214 |
|
215 def _check_for_dup_router_subnet(self, context, router_id, |
|
216 network_id, subnet_id, subnet_cidr): |
|
217 try: |
|
218 - rport_qry = context.session.query(models_v2.Port) |
|
219 - rports = rport_qry.filter_by( |
|
220 - device_id=router_id).all() |
|
221 + rports = self.get_ports(context, |
|
222 + filters={'device_id': [router_id]}) |
|
223 # its possible these ports on on the same network, but |
|
224 # different subnet |
|
225 new_ipnet = netaddr.IPNetwork(subnet_cidr) |
|
226 @@ -348,8 +353,9 @@ |
|
227 port['network_id'], |
|
228 subnet['id'], |
|
229 subnet['cidr']) |
|
230 - port.update({'device_id': router_id, |
|
231 - 'device_owner': DEVICE_OWNER_ROUTER_INTF}) |
|
232 + self.update_port(context, interface_info['port_id'], |
|
233 + {'device_id': router_id, |
|
234 + 'device_owner': DEVICE_OWNER_ROUTER_INTF}) |
|
235 elif 'subnet_id' in interface_info: |
|
236 subnet_id = interface_info['subnet_id'] |
|
237 subnet = self._get_subnet(context, subnet_id) |
|
238 @@ -394,7 +400,7 @@ |
|
239 subnet_id): |
|
240 subnet_db = self._get_subnet(context, subnet_id) |
|
241 subnet_cidr = netaddr.IPNetwork(subnet_db['cidr']) |
|
242 - fip_qry = context.session.query(FloatingIP) |
|
243 + fip_qry = context.session.query(self.FloatingIP) |
|
244 for fip_db in fip_qry.filter_by(router_id=router_id): |
|
245 if netaddr.IPAddress(fip_db['fixed_ip_address']) in subnet_cidr: |
|
246 raise l3.RouterInterfaceInUseByFloatingIP( |
|
247 @@ -440,22 +446,19 @@ |
|
248 subnet = self._get_subnet(context, subnet_id) |
|
249 found = False |
|
250 |
|
251 - try: |
|
252 - rport_qry = context.session.query(models_v2.Port) |
|
253 - ports = rport_qry.filter_by( |
|
254 - device_id=router_id, |
|
255 - device_owner=DEVICE_OWNER_ROUTER_INTF, |
|
256 - network_id=subnet['network_id']).all() |
|
257 - |
|
258 - for p in ports: |
|
259 - if p['fixed_ips'][0]['subnet_id'] == subnet_id: |
|
260 - port_id = p['id'] |
|
261 - _network_id = p['network_id'] |
|
262 - self.delete_port(context, p['id'], l3_port_check=False) |
|
263 - found = True |
|
264 - break |
|
265 - except exc.NoResultFound: |
|
266 - pass |
|
267 + filters = { |
|
268 + 'device_id': router_id, |
|
269 + 'device_owner': DEVICE_OWNER_ROUTER_INTF, |
|
270 + 'network_id': subnet['network_id'] |
|
271 + } |
|
272 + ports = self.get_ports(context, filters) |
|
273 + for p in ports: |
|
274 + if p['fixed_ips'][0]['subnet_id'] == subnet_id: |
|
275 + port_id = p['id'] |
|
276 + _network_id = p['network_id'] |
|
277 + self.delete_port(context, p['id'], l3_port_check=False) |
|
278 + found = True |
|
279 + break |
|
280 |
|
281 if not found: |
|
282 raise l3.RouterInterfaceNotFoundForSubnet(router_id=router_id, |
|
283 @@ -477,7 +480,7 @@ |
|
284 |
|
285 def _get_floatingip(self, context, id): |
|
286 try: |
|
287 - floatingip = self._get_by_id(context, FloatingIP, id) |
|
288 + floatingip = self._get_by_id(context, self.FloatingIP, id) |
|
289 except exc.NoResultFound: |
|
290 raise l3.FloatingIPNotFound(floatingip_id=id) |
|
291 except exc.MultipleResultsFound: |
|
292 @@ -505,19 +508,21 @@ |
|
293 raise q_exc.BadRequest(resource='floatingip', msg=msg) |
|
294 |
|
295 # find router interface ports on this network |
|
296 - router_intf_qry = context.session.query(models_v2.Port) |
|
297 - router_intf_ports = router_intf_qry.filter_by( |
|
298 - network_id=internal_port['network_id'], |
|
299 - device_owner=DEVICE_OWNER_ROUTER_INTF) |
|
300 + router_intf_filter = { |
|
301 + 'network_id': internal_port['network_id'], |
|
302 + 'device_owner': DEVICE_OWNER_ROUTER_INTF |
|
303 + } |
|
304 + router_intf_ports = self.get_ports(context, filters=router_intf_filter) |
|
305 |
|
306 for intf_p in router_intf_ports: |
|
307 if intf_p['fixed_ips'][0]['subnet_id'] == internal_subnet_id: |
|
308 router_id = intf_p['device_id'] |
|
309 - router_gw_qry = context.session.query(models_v2.Port) |
|
310 - has_gw_port = router_gw_qry.filter_by( |
|
311 - network_id=external_network_id, |
|
312 - device_id=router_id, |
|
313 - device_owner=DEVICE_OWNER_ROUTER_GW).count() |
|
314 + filters = { |
|
315 + 'network_id': external_network_id, |
|
316 + 'device_id': router_id, |
|
317 + 'device_owner': DEVICE_OWNER_ROUTER_GW |
|
318 + } |
|
319 + has_gw_port = self.get_ports_count(context, filters) |
|
320 if has_gw_port: |
|
321 return router_id |
|
322 |
|
323 @@ -578,13 +583,13 @@ |
|
324 floating_network_id) |
|
325 # confirm that this router has a floating |
|
326 # ip enabled gateway with support for this floating IP network |
|
327 - try: |
|
328 - port_qry = context.elevated().session.query(models_v2.Port) |
|
329 - ports = port_qry.filter_by( |
|
330 - network_id=floating_network_id, |
|
331 - device_id=router_id, |
|
332 - device_owner=DEVICE_OWNER_ROUTER_GW).one() |
|
333 - except exc.NoResultFound: |
|
334 + filters = { |
|
335 + 'network_id': floating_network_id, |
|
336 + 'device_id': router_id, |
|
337 + 'device_owner': DEVICE_OWNER_ROUTER_GW |
|
338 + } |
|
339 + ports = self.get_ports(context.elevated(), filters) |
|
340 + if not ports: |
|
341 raise l3.ExternalGatewayForFloatingIPNotFound( |
|
342 subnet_id=internal_subnet_id, |
|
343 port_id=internal_port['id']) |
|
344 @@ -602,7 +607,7 @@ |
|
345 context, |
|
346 fip, |
|
347 floatingip_db['floating_network_id']) |
|
348 - fip_qry = context.session.query(FloatingIP) |
|
349 + fip_qry = context.session.query(self.FloatingIP) |
|
350 try: |
|
351 fip_qry.filter_by( |
|
352 fixed_port_id=fip['port_id'], |
|
353 @@ -653,7 +658,7 @@ |
|
354 |
|
355 floating_fixed_ip = external_port['fixed_ips'][0] |
|
356 floating_ip_address = floating_fixed_ip['ip_address'] |
|
357 - floatingip_db = FloatingIP( |
|
358 + floatingip_db = self.FloatingIP( |
|
359 id=fip_id, |
|
360 tenant_id=tenant_id, |
|
361 floating_network_id=fip['floating_network_id'], |
|
362 @@ -731,7 +736,7 @@ |
|
363 if key in filters: |
|
364 filters[val] = filters.pop(key) |
|
365 |
|
366 - return self._get_collection(context, FloatingIP, |
|
367 + return self._get_collection(context, self.FloatingIP, |
|
368 self._make_floatingip_dict, |
|
369 filters=filters, fields=fields, |
|
370 sorts=sorts, |
|
371 @@ -740,7 +745,7 @@ |
|
372 page_reverse=page_reverse) |
|
373 |
|
374 def get_floatingips_count(self, context, filters=None): |
|
375 - return self._get_collection_count(context, FloatingIP, |
|
376 + return self._get_collection_count(context, self.FloatingIP, |
|
377 filters=filters) |
|
378 |
|
379 def prevent_l3_port_deletion(self, context, port_id): |
|
380 @@ -770,7 +775,7 @@ |
|
381 def disassociate_floatingips(self, context, port_id): |
|
382 with context.session.begin(subtransactions=True): |
|
383 try: |
|
384 - fip_qry = context.session.query(FloatingIP) |
|
385 + fip_qry = context.session.query(self.FloatingIP) |
|
386 floating_ip = fip_qry.filter_by(fixed_port_id=port_id).one() |
|
387 router_id = floating_ip['router_id'] |
|
388 floating_ip.update({'fixed_port_id': None, |
|
389 @@ -874,14 +879,17 @@ |
|
390 if it is None, all of routers will be queried. |
|
391 @return: a list of dicted routers with dicted gw_port populated if any |
|
392 """ |
|
393 - router_query = context.session.query(Router) |
|
394 + router_query = context.session.query(self.Router) |
|
395 if router_ids: |
|
396 if 1 == len(router_ids): |
|
397 - router_query = router_query.filter(Router.id == router_ids[0]) |
|
398 + router_query = \ |
|
399 + router_query.filter(self.Router.id == router_ids[0]) |
|
400 else: |
|
401 - router_query = router_query.filter(Router.id.in_(router_ids)) |
|
402 + router_query = \ |
|
403 + router_query.filter(self.Router.id.in_(router_ids)) |
|
404 if active is not None: |
|
405 - router_query = router_query.filter(Router.admin_state_up == active) |
|
406 + router_query = \ |
|
407 + router_query.filter(self.Router.admin_state_up == active) |
|
408 routers = router_query.all() |
|
409 gw_port_ids = [] |
|
410 if not routers: |