db312a2886
This commit builds on top of part 1 to introduce support for creating dynamic network segments in ML2. Change-Id: I399e1569baae6f24054aac15c4c51a2e44a20e5b Partially implements: Blueprint ml2-type-driver-refactor
186 lines
5.9 KiB
Python
186 lines
5.9 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.common import constants
|
|
from neutron.extensions import portbindings
|
|
from neutron.openstack.common import jsonutils
|
|
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, binding,
|
|
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 = binding
|
|
if original_port:
|
|
self._original_bound_segment_id = self._binding.segment
|
|
self._original_bound_driver = self._binding.driver
|
|
else:
|
|
self._original_bound_segment_id = None
|
|
self._original_bound_driver = None
|
|
self._new_port_status = None
|
|
|
|
@property
|
|
def current(self):
|
|
return self._port
|
|
|
|
@property
|
|
def original(self):
|
|
return self._original_port
|
|
|
|
@property
|
|
def status(self):
|
|
return self._port['status']
|
|
|
|
@property
|
|
def original_status(self):
|
|
return self._original_port['status']
|
|
|
|
@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
|
|
|
|
@property
|
|
def original_bound_segment(self):
|
|
if self._original_bound_segment_id:
|
|
for segment in self._network_context.network_segments:
|
|
if segment[api.ID] == self._original_bound_segment_id:
|
|
return segment
|
|
|
|
@property
|
|
def host(self):
|
|
return self._port.get(portbindings.HOST_ID)
|
|
|
|
@property
|
|
def original_host(self):
|
|
return self._original_port.get(portbindings.HOST_ID)
|
|
|
|
@property
|
|
def bound_driver(self):
|
|
return self._binding.driver
|
|
|
|
@property
|
|
def original_bound_driver(self):
|
|
return self._original_bound_driver
|
|
|
|
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, vif_details,
|
|
status=None):
|
|
# TODO(rkukura) Verify binding allowed, segment in network
|
|
self._binding.segment = segment_id
|
|
self._binding.vif_type = vif_type
|
|
self._binding.vif_details = jsonutils.dumps(vif_details)
|
|
self._new_port_status = status
|
|
|
|
def allocate_dynamic_segment(self, segment):
|
|
network_id = self._network_context.current['id']
|
|
|
|
return self._plugin.type_manager.allocate_dynamic_segment(
|
|
self._plugin_context.session, network_id, segment)
|
|
|
|
def release_dynamic_segment(self, segment_id):
|
|
return self._plugin.type_manager.release_dynamic_segment(
|
|
self._plugin_context.session, segment_id)
|
|
|
|
|
|
class DvrPortContext(PortContext):
|
|
|
|
def __init__(self, plugin, plugin_context, port, network, binding,
|
|
original_port=None):
|
|
super(DvrPortContext, self).__init__(
|
|
plugin, plugin_context, port, network, binding,
|
|
original_port=original_port)
|
|
|
|
@property
|
|
def host(self):
|
|
if self._port['device_owner'] == constants.DEVICE_OWNER_DVR_INTERFACE:
|
|
return self._binding.host
|
|
|
|
return super(DvrPortContext, self).host
|
|
|
|
@property
|
|
def status(self):
|
|
if self._port['device_owner'] == constants.DEVICE_OWNER_DVR_INTERFACE:
|
|
return self._binding.status
|
|
|
|
return super(DvrPortContext, self).status
|