From c3b2c2a9a22bac5cf17813c589444d3abebaa23b Mon Sep 17 00:00:00 2001 From: Wojciech Dec Date: Tue, 16 Aug 2016 19:27:01 +0200 Subject: Adding Mitaka networking-old module with the ODL topology based port binding resolution mechanism from https://review.openstack.org/333186 Change-Id: I10d400aac9bb639c146527f0f93e6925cb74d9de Signed-off-by: Wojciech Dec --- networking-odl/networking_odl/l3/l3_odl.py | 189 +++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 networking-odl/networking_odl/l3/l3_odl.py (limited to 'networking-odl/networking_odl/l3/l3_odl.py') diff --git a/networking-odl/networking_odl/l3/l3_odl.py b/networking-odl/networking_odl/l3/l3_odl.py new file mode 100644 index 0000000..e06e335 --- /dev/null +++ b/networking-odl/networking_odl/l3/l3_odl.py @@ -0,0 +1,189 @@ +# +# Copyright (C) 2013 Red Hat, Inc. +# +# 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. +# + +from oslo_config import cfg +from oslo_log import log as logging + +from neutron.api.rpc.agentnotifiers import l3_rpc_agent_api +from neutron.api.rpc.handlers import l3_rpc +from neutron.common import rpc as n_rpc +from neutron.common import topics +from neutron.db import extraroute_db +from neutron.db import l3_agentschedulers_db +from neutron.db import l3_dvr_db +from neutron.db import l3_gwmode_db +from neutron.plugins.common import constants +from neutron_lib import constants as q_const + +from networking_odl.common import client as odl_client +from networking_odl.common import utils as odl_utils + +try: + from neutron.db.db_base_plugin_v2 import common_db_mixin +except ImportError as e: + # the change set ofece8cc2e9aae1610a325d0c206e38da3da9a0a1a + # the Change-Id of I1eac61c258541bca80e14be4b7c75519a014ffae + # db_base_plugin_v2.common_db_mixin was removed + from neutron.db import common_db_mixin + + +cfg.CONF.import_group('ml2_odl', 'networking_odl.common.config') +LOG = logging.getLogger(__name__) +ROUTERS = 'routers' +FLOATINGIPS = 'floatingips' + + +class OpenDaylightL3RouterPlugin( + common_db_mixin.CommonDbMixin, + extraroute_db.ExtraRoute_db_mixin, + l3_dvr_db.L3_NAT_with_dvr_db_mixin, + l3_gwmode_db.L3_NAT_db_mixin, + l3_agentschedulers_db.L3AgentSchedulerDbMixin): + + """Implementation of the OpenDaylight L3 Router Service Plugin. + + This class implements a L3 service plugin that provides + router and floatingip resources and manages associated + request/response. + """ + supported_extension_aliases = ["dvr", "router", "ext-gw-mode", + "extraroute"] + + def __init__(self): + self.setup_rpc() + self.client = odl_client.OpenDaylightRestClient.create_client() + + def setup_rpc(self): + self.topic = topics.L3PLUGIN + self.conn = n_rpc.create_connection() + self.agent_notifiers.update( + {q_const.AGENT_TYPE_L3: l3_rpc_agent_api.L3AgentNotifyAPI()}) + self.endpoints = [l3_rpc.L3RpcCallback()] + self.conn.create_consumer(self.topic, self.endpoints, + fanout=False) + self.conn.consume_in_threads() + + def get_plugin_type(self): + return constants.L3_ROUTER_NAT + + def get_plugin_description(self): + """returns string description of the plugin.""" + return ("L3 Router Service Plugin for basic L3 forwarding" + " using OpenDaylight") + + def filter_update_router_attributes(self, router): + """Filter out router attributes for an update operation.""" + odl_utils.try_del(router, ['id', 'tenant_id', 'status']) + + def create_router(self, context, router): + router_dict = super(OpenDaylightL3RouterPlugin, self).create_router( + context, router) + url = ROUTERS + self.client.sendjson('post', url, {ROUTERS[:-1]: router_dict}) + return router_dict + + def update_router(self, context, id, router): + router_dict = super(OpenDaylightL3RouterPlugin, self).update_router( + context, id, router) + url = ROUTERS + "/" + id + resource = router_dict.copy() + self.filter_update_router_attributes(resource) + self.client.sendjson('put', url, {ROUTERS[:-1]: resource}) + return router_dict + + def delete_router(self, context, id): + super(OpenDaylightL3RouterPlugin, self).delete_router(context, id) + url = ROUTERS + "/" + id + self.client.sendjson('delete', url, None) + + def create_floatingip(self, context, floatingip, + initial_status=q_const.FLOATINGIP_STATUS_ACTIVE): + fip_dict = super(OpenDaylightL3RouterPlugin, self).create_floatingip( + context, floatingip, initial_status) + url = FLOATINGIPS + self.client.sendjson('post', url, {FLOATINGIPS[:-1]: fip_dict}) + return fip_dict + + def update_floatingip(self, context, id, floatingip): + with context.session.begin(subtransactions=True): + fip_dict = super(OpenDaylightL3RouterPlugin, + self).update_floatingip(context, id, floatingip) + # Update status based on association + if fip_dict.get('port_id') is None: + fip_dict['status'] = q_const.FLOATINGIP_STATUS_DOWN + else: + fip_dict['status'] = q_const.FLOATINGIP_STATUS_ACTIVE + self.update_floatingip_status(context, id, fip_dict['status']) + + url = FLOATINGIPS + "/" + id + self.client.sendjson('put', url, {FLOATINGIPS[:-1]: fip_dict}) + return fip_dict + + def delete_floatingip(self, context, id): + super(OpenDaylightL3RouterPlugin, self).delete_floatingip(context, id) + url = FLOATINGIPS + "/" + id + self.client.sendjson('delete', url, None) + + def add_router_interface(self, context, router_id, interface_info): + new_router = super( + OpenDaylightL3RouterPlugin, self).add_router_interface( + context, router_id, interface_info) + url = ROUTERS + "/" + router_id + "/add_router_interface" + router_dict = self._generate_router_dict(router_id, interface_info, + new_router) + self.client.sendjson('put', url, router_dict) + return new_router + + def remove_router_interface(self, context, router_id, interface_info): + new_router = super( + OpenDaylightL3RouterPlugin, self).remove_router_interface( + context, router_id, interface_info) + url = ROUTERS + "/" + router_id + "/remove_router_interface" + router_dict = self._generate_router_dict(router_id, interface_info, + new_router) + self.client.sendjson('put', url, router_dict) + return new_router + + def _generate_router_dict(self, router_id, interface_info, new_router): + # Get network info for the subnet that is being added to the router. + # Check if the interface information is by port-id or subnet-id + add_by_port, add_by_sub = self._validate_interface_info(interface_info) + if add_by_sub: + _port_id = new_router['port_id'] + _subnet_id = interface_info['subnet_id'] + elif add_by_port: + _port_id = interface_info['port_id'] + _subnet_id = new_router['subnet_id'] + + router_dict = {'subnet_id': _subnet_id, + 'port_id': _port_id, + 'id': router_id, + 'tenant_id': new_router['tenant_id']} + + return router_dict + + dvr_deletens_if_no_port_warned = False + + def dvr_deletens_if_no_port(self, context, port_id): + # TODO(yamahata): implement this method or delete this logging + # For now, this is defined to avoid attribute exception + # Since ODL L3 does not create namespaces, this is always going to + # be a noop. When it is confirmed, delete this comment and logging + if not self.dvr_deletens_if_no_port_warned: + LOG.debug('dvr is not suported yet. ' + 'this method needs to be implemented') + self.dvr_deletens_if_no_port_warned = True + return [] -- cgit 1.2.3-korg