From 4979a23b8b2c0094ced98cf05eebb692d6609937 Mon Sep 17 00:00:00 2001 From: Wojciech Dec Date: Wed, 17 Aug 2016 13:14:23 +0200 Subject: Correcting networking-odl to mitaka/stable + app topology patch Change-Id: Iddcd8dda2d49fcdd8e0f37a1d052a6fa8a24b035 Signed-off-by: Wojciech Dec --- .../networking_odl/ml2/pseudo_agentdb_binding.py | 263 --------------------- 1 file changed, 263 deletions(-) delete mode 100644 networking-odl/networking_odl/ml2/pseudo_agentdb_binding.py (limited to 'networking-odl/networking_odl/ml2/pseudo_agentdb_binding.py') diff --git a/networking-odl/networking_odl/ml2/pseudo_agentdb_binding.py b/networking-odl/networking_odl/ml2/pseudo_agentdb_binding.py deleted file mode 100644 index d24bd55..0000000 --- a/networking-odl/networking_odl/ml2/pseudo_agentdb_binding.py +++ /dev/null @@ -1,263 +0,0 @@ -# Copyright (c) 2016 OpenStack Foundation -# 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 logging -from neutron_lib import constants as nl_const -from requests import exceptions -import six.moves.urllib.parse as urlparse -from string import Template - -from oslo_config import cfg -from oslo_log import log -from oslo_serialization import jsonutils - -from neutron import context -from neutron.extensions import portbindings -from neutron import manager -from neutron.plugins.ml2 import driver_api - -from networking_odl._i18n import _LE, _LI, _LW -from networking_odl.common import client as odl_client -from networking_odl.journal import maintenance as mt -from networking_odl.ml2 import port_binding - -cfg.CONF.import_group('ml2_odl', 'networking_odl.common.config') -LOG = log.getLogger(__name__) - - -class PseudoAgentDBBindingController(port_binding.PortBindingController): - """Switch agnostic Port binding controller for OpenDayLight.""" - - AGENTDB_BINARY = 'neutron-odlagent-portbinding' - L2_TYPE = "ODL L2" - - # TODO(mzmalick): binary, topic and resource_versions to be provided - # by ODL, Pending ODL NB patches. - agentdb_row = { - 'binary': AGENTDB_BINARY, - 'host': '', - 'topic': nl_const.L2_AGENT_TOPIC, - 'configurations': {}, - 'resource_versions': '', - 'agent_type': L2_TYPE, - 'start_flag': True} - # We are not running host agents, so above start_flag is redundant - - def __init__(self, hostconf_uri=None, db_plugin=None): - """Initialization.""" - LOG.debug("Initializing ODL Port Binding Controller") - - if not hostconf_uri: - # extract host/port from ODL URL and append hostconf_uri path - hostconf_uri = self._make_hostconf_uri( - cfg.CONF.ml2_odl.url, cfg.CONF.ml2_odl.odl_hostconf_uri) - - LOG.debug("ODLPORTBINDING hostconfigs URI: %s", hostconf_uri) - - # TODO(mzmalick): disable port-binding for ODL lightweight testing - self.odl_rest_client = odl_client.OpenDaylightRestClient.create_client( - url=hostconf_uri) - - # Neutron DB plugin instance - self.agents_db = db_plugin - - # Start polling ODL restconf using maintenance thread. - # default: 30s (should be <= agent keep-alive poll interval) - self._start_maintenance_thread(cfg.CONF.ml2_odl.restconf_poll_interval) - - def _make_hostconf_uri(self, odl_url=None, path=''): - """Make ODL hostconfigs URI with host/port extraced from ODL_URL.""" - # NOTE(yamahata): for unit test. - odl_url = odl_url or 'http://localhost:8080/' - - # extract ODL_IP and ODL_PORT from ODL_ENDPOINT and append path - # urlsplit and urlunparse don't throw exceptions - purl = urlparse.urlsplit(odl_url) - return urlparse.urlunparse((purl.scheme, purl.netloc, - path, '', '', '')) - # - # TODO(mzmalick): - # 1. implement websockets for ODL hostconfig events - # - - def _start_maintenance_thread(self, poll_interval): - self._mainth = mt.MaintenanceThread() - self._mainth.maintenance_interval = poll_interval - self._mainth.register_operation(self._get_and_update_hostconfigs) - self._mainth.start() - - def _rest_get_hostconfigs(self): - try: - response = self.odl_rest_client.get() - response.raise_for_status() - hostconfigs = response.json()['hostconfigs']['hostconfig'] - except exceptions.ConnectionError: - LOG.error(_LE("Cannot connect to the Opendaylight Controller"), - exc_info=True) - return None - except KeyError: - LOG.error(_LE("got invalid hostconfigs"), - exc_info=True) - return None - except Exception: - LOG.warning(_LW("REST/GET odl hostconfig failed, "), - exc_info=True) - return None - else: - if LOG.isEnabledFor(logging.DEBUG): - _hconfig_str = jsonutils.dumps( - response, sort_keys=True, indent=4, separators=(',', ': ')) - LOG.debug("ODLPORTBINDING hostconfigs:\n%s", _hconfig_str) - - return hostconfigs - - def _get_and_update_hostconfigs(self, session=None): - LOG.info(_LI("REST/GET hostconfigs from ODL")) - - hostconfigs = self._rest_get_hostconfigs() - - if not hostconfigs: - LOG.warning(_LW("ODL hostconfigs REST/GET failed, " - "will retry on next poll")) - return # retry on next poll - - self._update_agents_db(hostconfigs=hostconfigs) - - def _get_neutron_db_plugin(self): - if (not self.agents_db) and manager.NeutronManager.has_instance(): - self.agents_db = manager.NeutronManager.get_plugin() - return self.agents_db - - def _update_agents_db(self, hostconfigs): - LOG.debug("ODLPORTBINDING Updating agents DB with ODL hostconfigs") - - agents_db = self._get_neutron_db_plugin() - - if not agents_db: # if ML2 is still initializing - LOG.warning(_LW("ML2 still initializing, Will retry agentdb" - " update on next poll")) - return # Retry on next poll - - for host_config in hostconfigs: - try: - self.agentdb_row['host'] = host_config['host-id'] - self.agentdb_row['agent_type'] = host_config['host-type'] - self.agentdb_row['configurations'] = host_config['config'] - - agents_db.create_or_update_agent( - context.get_admin_context(), self.agentdb_row) - except Exception: - LOG.exception(_LE("Unable to update agentdb.")) - continue # try next hostcofig - - def _substitute_hconfig_tmpl(self, port_context, hconfig): - # TODO(mzmalick): Explore options for inlines string splicing of - # port-id to 14 bytes as required by vhostuser types - subs_ids = { - # $IDENTIFER string substitution in hostconfigs JSON string - 'PORT_ID': port_context.current['id'][:14] - } - - # Substitute identifiers and Convert JSON string to dict - hconfig_conf_json = Template(hconfig['configurations']) - substituted_str = hconfig_conf_json.safe_substitute(subs_ids) - hconfig['configurations'] = jsonutils.loads(substituted_str) - - return hconfig - - def bind_port(self, port_context): - """bind port using ODL host configuration.""" - # Get all ODL hostconfigs for this host and type - agentdb = port_context.host_agents(self.L2_TYPE) - - if not agentdb: - LOG.warning(_LW("No valid hostconfigs in agentsdb for host %s"), - port_context.host) - return - - for raw_hconfig in agentdb: - # do any $identifier substitution - hconfig = self._substitute_hconfig_tmpl(port_context, raw_hconfig) - - # Found ODL hostconfig for this host in agentdb - LOG.debug("ODLPORTBINDING bind port with hostconfig: %s", hconfig) - - if self._hconfig_bind_port(port_context, hconfig): - break # Port binding suceeded! - else: # Port binding failed! - LOG.warning(_LW("Failed to bind Port %(pid)s for host " - "%(host)s on network %(network)s."), { - 'pid': port_context.current['id'], - 'host': port_context.host, - 'network': port_context.network.current['id']}) - else: # No hostconfig found for host in agentdb. - LOG.warning(_LW("No ODL hostconfigs for host %s found in agentdb"), - port_context.host) - - def _hconfig_bind_port(self, port_context, hconfig): - """bind port after validating odl host configuration.""" - valid_segment = None - - for segment in port_context.segments_to_bind: - if self._is_valid_segment(segment, hconfig['configurations']): - valid_segment = segment - break - else: - LOG.debug("No valid segments found!") - return False - - confs = hconfig['configurations']['supported_vnic_types'] - - # nova provides vnic_type in port_context to neutron. - # neutron provides supported vif_type for binding based on vnic_type - # in this case ODL hostconfigs has the vif_type to bind for vnic_type - vnic_type = port_context.current.get(portbindings.VNIC_TYPE) - - if vnic_type != portbindings.VNIC_NORMAL: - LOG.error(_LE("Binding failed: unsupported VNIC %s"), vnic_type) - return False - - for conf in confs: - if conf["vnic_type"] == vnic_type: - vif_type = conf.get('vif_type', portbindings.VIF_TYPE_OVS) - LOG.debug("Binding vnic:'%s' to vif:'%s'", vnic_type, vif_type) - break - else: - vif_type = portbindings.VIF_TYPE_OVS # default: OVS - LOG.warning(_LW("No supported vif type found for host %s!, " - "defaulting to OVS"), port_context.host) - - vif_details = conf.get('vif_details', {}) - - if not vif_details: # empty vif_details could be trouble, warn. - LOG.warning(_LW("hostconfig:vif_details was empty!")) - - LOG.debug("Bind port %(port)s on network %(network)s with valid " - "segment %(segment)s and VIF type %(vif_type)r " - "VIF details %(vif_details)r.", - {'port': port_context.current['id'], - 'network': port_context.network.current['id'], - 'segment': valid_segment, 'vif_type': vif_type, - 'vif_details': vif_details}) - - port_context.set_binding(valid_segment[driver_api.ID], vif_type, - vif_details, - status=nl_const.PORT_STATUS_ACTIVE) - return True - - def _is_valid_segment(self, segment, conf): - """Verify a segment is supported by ODL.""" - network_type = segment[driver_api.NETWORK_TYPE] - return network_type in conf['allowed_network_types'] -- cgit 1.2.3-korg