0f0499b89e
The ml2 plugin uses mechanism drivers to determine which network segment and what VIF driver to use for a port. Mechanism drivers supporting the openvswitch, linuxbridge, and hyperv agents are added. The binding:host attribute is set on ports belonging to the dhcp and l3 agents so that they can be bound. To use with devstack until it is updated, set "Q_ML2_PLUGIN_MECHANISM_DRIVERS=openvswitch,linuxbridge" in localrc. The hyperv L2 agent does not currently implement the agents_db RPC, and will therefore not work with its ml2 mechanism driver. This issue will be tracked as a bug to be fixed in a separate merge. implements blueprint: ml2-portbinding Change-Id: Icb9c70d8b0d7fcb34b57adc760bb713b740e5dad
115 lines
3.8 KiB
Python
115 lines
3.8 KiB
Python
# Copyright (c) 2013 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.
|
|
|
|
from neutron.plugins.ml2 import db
|
|
from neutron.plugins.ml2 import driver_api as api
|
|
|
|
|
|
class MechanismDriverContext(object):
|
|
"""MechanismDriver context base class."""
|
|
def __init__(self, plugin, plugin_context):
|
|
self._plugin = plugin
|
|
# This temporarily creates a reference loop, but the
|
|
# lifetime of PortContext is limited to a single
|
|
# method call of the plugin.
|
|
self._plugin_context = plugin_context
|
|
|
|
|
|
class NetworkContext(MechanismDriverContext, api.NetworkContext):
|
|
|
|
def __init__(self, plugin, plugin_context, network,
|
|
original_network=None):
|
|
super(NetworkContext, self).__init__(plugin, plugin_context)
|
|
self._network = network
|
|
self._original_network = original_network
|
|
self._segments = db.get_network_segments(plugin_context.session,
|
|
network['id'])
|
|
|
|
@property
|
|
def current(self):
|
|
return self._network
|
|
|
|
@property
|
|
def original(self):
|
|
return self._original_network
|
|
|
|
@property
|
|
def network_segments(self):
|
|
return self._segments
|
|
|
|
|
|
class SubnetContext(MechanismDriverContext, api.SubnetContext):
|
|
|
|
def __init__(self, plugin, plugin_context, subnet, original_subnet=None):
|
|
super(SubnetContext, self).__init__(plugin, plugin_context)
|
|
self._subnet = subnet
|
|
self._original_subnet = original_subnet
|
|
|
|
@property
|
|
def current(self):
|
|
return self._subnet
|
|
|
|
@property
|
|
def original(self):
|
|
return self._original_subnet
|
|
|
|
|
|
class PortContext(MechanismDriverContext, api.PortContext):
|
|
|
|
def __init__(self, plugin, plugin_context, port, network,
|
|
original_port=None):
|
|
super(PortContext, self).__init__(plugin, plugin_context)
|
|
self._port = port
|
|
self._original_port = original_port
|
|
self._network_context = NetworkContext(plugin, plugin_context,
|
|
network)
|
|
self._binding = db.ensure_port_binding(plugin_context.session,
|
|
port['id'])
|
|
|
|
@property
|
|
def current(self):
|
|
return self._port
|
|
|
|
@property
|
|
def original(self):
|
|
return self._original_port
|
|
|
|
@property
|
|
def network(self):
|
|
return self._network_context
|
|
|
|
@property
|
|
def bound_segment(self):
|
|
id = self._binding.segment
|
|
if id:
|
|
for segment in self._network_context.network_segments:
|
|
if segment[api.ID] == id:
|
|
return segment
|
|
|
|
def host_agents(self, agent_type):
|
|
return self._plugin.get_agents(self._plugin_context,
|
|
filters={'agent_type': [agent_type],
|
|
'host': [self._binding.host]})
|
|
|
|
def set_binding(self, segment_id, vif_type, cap_port_filter):
|
|
# REVISIT(rkukura): Pass extensible list of capabilities? Move
|
|
# vif_type and capabilities to methods on the bound mechanism
|
|
# driver?
|
|
|
|
# TODO(rkukura) Verify binding allowed, segment in network
|
|
self._binding.segment = segment_id
|
|
self._binding.vif_type = vif_type
|
|
self._binding.cap_port_filter = cap_port_filter
|