diff --git a/neutron_lib/plugins/ml2/__init__.py b/neutron_lib/plugins/ml2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/neutron_lib/plugins/ml2/api.py b/neutron_lib/plugins/ml2/api.py new file mode 100644 index 0000000..d8a7d5f --- /dev/null +++ b/neutron_lib/plugins/ml2/api.py @@ -0,0 +1,412 @@ +# 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 abc +import six + + +# The following keys are used in the segment dictionaries passed via +# the driver API. +ID = 'id' +NETWORK_TYPE = 'network_type' +PHYSICAL_NETWORK = 'physical_network' +SEGMENTATION_ID = 'segmentation_id' +MTU = 'mtu' + +# The following keys are used in the binding level dictionaries +# available via the binding_levels and original_binding_levels +# PortContext properties. +BOUND_DRIVER = 'bound_driver' +BOUND_SEGMENT = 'bound_segment' + + +@six.add_metaclass(abc.ABCMeta) +class MechanismDriver(object): + """Define stable abstract interface for ML2 mechanism drivers. + + A mechanism driver is called on the creation, update, and deletion + of networks and ports. For every event, there are two methods that + get called - one within the database transaction (method suffix of + _precommit), one right afterwards (method suffix of _postcommit). + + Exceptions raised by methods called inside the transaction can + rollback, but should not make any blocking calls (for example, + REST requests to an outside controller). Methods called after + transaction commits can make blocking external calls, though these + will block the entire process. Exceptions raised in calls after + the transaction commits may cause the associated resource to be + deleted. + + Because rollback outside of the transaction is not done in the + update network/port case, all data validation must be done within + methods that are part of the database transaction. + """ + + @abc.abstractmethod + def initialize(self): + """Perform driver initialization. + + Called after all drivers have been loaded and the database has + been initialized. No abstract methods defined below will be + called prior to this method being called. + """ + pass + + def create_network_precommit(self, context): + """Allocate resources for a new network. + + :param context: NetworkContext instance describing the new + network. + + Create a new network, allocating resources as necessary in the + database. Called inside transaction context on session. Call + cannot block. Raising an exception will result in a rollback + of the current transaction. + """ + pass + + def create_network_postcommit(self, context): + """Create a network. + + :param context: NetworkContext instance describing the new + network. + + Called after the transaction commits. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Raising an exception will + cause the deletion of the resource. + """ + pass + + def update_network_precommit(self, context): + """Update resources of a network. + + :param context: NetworkContext instance describing the new + state of the network, as well as the original state prior + to the update_network call. + + Update values of a network, updating the associated resources + in the database. Called inside transaction context on session. + Raising an exception will result in rollback of the + transaction. + + update_network_precommit is called for all changes to the + network state. It is up to the mechanism driver to ignore + state or state changes that it does not know or care about. + """ + pass + + def update_network_postcommit(self, context): + """Update a network. + + :param context: NetworkContext instance describing the new + state of the network, as well as the original state prior + to the update_network call. + + Called after the transaction commits. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Raising an exception will + cause the deletion of the resource. + + update_network_postcommit is called for all changes to the + network state. It is up to the mechanism driver to ignore + state or state changes that it does not know or care about. + """ + pass + + def delete_network_precommit(self, context): + """Delete resources for a network. + + :param context: NetworkContext instance describing the current + state of the network, prior to the call to delete it. + + Delete network resources previously allocated by this + mechanism driver for a network. Called inside transaction + context on session. Runtime errors are not expected, but + raising an exception will result in rollback of the + transaction. + """ + pass + + def delete_network_postcommit(self, context): + """Delete a network. + + :param context: NetworkContext instance describing the current + state of the network, prior to the call to delete it. + + Called after the transaction commits. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Runtime errors are not + expected, and will not prevent the resource from being + deleted. + """ + pass + + def create_subnet_precommit(self, context): + """Allocate resources for a new subnet. + + :param context: SubnetContext instance describing the new + subnet. + + Create a new subnet, allocating resources as necessary in the + database. Called inside transaction context on session. Call + cannot block. Raising an exception will result in a rollback + of the current transaction. + """ + pass + + def create_subnet_postcommit(self, context): + """Create a subnet. + + :param context: SubnetContext instance describing the new + subnet. + + Called after the transaction commits. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Raising an exception will + cause the deletion of the resource. + """ + pass + + def update_subnet_precommit(self, context): + """Update resources of a subnet. + + :param context: SubnetContext instance describing the new + state of the subnet, as well as the original state prior + to the update_subnet call. + + Update values of a subnet, updating the associated resources + in the database. Called inside transaction context on session. + Raising an exception will result in rollback of the + transaction. + + update_subnet_precommit is called for all changes to the + subnet state. It is up to the mechanism driver to ignore + state or state changes that it does not know or care about. + """ + pass + + def update_subnet_postcommit(self, context): + """Update a subnet. + + :param context: SubnetContext instance describing the new + state of the subnet, as well as the original state prior + to the update_subnet call. + + Called after the transaction commits. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Raising an exception will + cause the deletion of the resource. + + update_subnet_postcommit is called for all changes to the + subnet state. It is up to the mechanism driver to ignore + state or state changes that it does not know or care about. + """ + pass + + def delete_subnet_precommit(self, context): + """Delete resources for a subnet. + + :param context: SubnetContext instance describing the current + state of the subnet, prior to the call to delete it. + + Delete subnet resources previously allocated by this + mechanism driver for a subnet. Called inside transaction + context on session. Runtime errors are not expected, but + raising an exception will result in rollback of the + transaction. + """ + pass + + def delete_subnet_postcommit(self, context): + """Delete a subnet. + + :param context: SubnetContext instance describing the current + state of the subnet, prior to the call to delete it. + + Called after the transaction commits. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Runtime errors are not + expected, and will not prevent the resource from being + deleted. + """ + pass + + def create_port_precommit(self, context): + """Allocate resources for a new port. + + :param context: PortContext instance describing the port. + + Create a new port, allocating resources as necessary in the + database. Called inside transaction context on session. Call + cannot block. Raising an exception will result in a rollback + of the current transaction. + """ + pass + + def create_port_postcommit(self, context): + """Create a port. + + :param context: PortContext instance describing the port. + + Called after the transaction completes. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Raising an exception will + result in the deletion of the resource. + """ + pass + + def update_port_precommit(self, context): + """Update resources of a port. + + :param context: PortContext instance describing the new + state of the port, as well as the original state prior + to the update_port call. + + Called inside transaction context on session to complete a + port update as defined by this mechanism driver. Raising an + exception will result in rollback of the transaction. + + update_port_precommit is called for all changes to the port + state. It is up to the mechanism driver to ignore state or + state changes that it does not know or care about. + """ + pass + + def update_port_postcommit(self, context): + """Update a port. + + :param context: PortContext instance describing the new + state of the port, as well as the original state prior + to the update_port call. + + Called after the transaction completes. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Raising an exception will + result in the deletion of the resource. + + update_port_postcommit is called for all changes to the port + state. It is up to the mechanism driver to ignore state or + state changes that it does not know or care about. + """ + pass + + def delete_port_precommit(self, context): + """Delete resources of a port. + + :param context: PortContext instance describing the current + state of the port, prior to the call to delete it. + + Called inside transaction context on session. Runtime errors + are not expected, but raising an exception will result in + rollback of the transaction. + """ + pass + + def delete_port_postcommit(self, context): + """Delete a port. + + :param context: PortContext instance describing the current + state of the port, prior to the call to delete it. + + Called after the transaction completes. Call can block, though + will block the entire process so care should be taken to not + drastically affect performance. Runtime errors are not + expected, and will not prevent the resource from being + deleted. + """ + pass + + def bind_port(self, context): + """Attempt to bind a port. + + :param context: PortContext instance describing the port + + This method is called outside any transaction to attempt to + establish a port binding using this mechanism driver. Bindings + may be created at each of multiple levels of a hierarchical + network, and are established from the top level downward. At + each level, the mechanism driver determines whether it can + bind to any of the network segments in the + context.segments_to_bind property, based on the value of the + context.host property, any relevant port or network + attributes, and its own knowledge of the network topology. At + the top level, context.segments_to_bind contains the static + segments of the port's network. At each lower level of + binding, it contains static or dynamic segments supplied by + the driver that bound at the level above. If the driver is + able to complete the binding of the port to any segment in + context.segments_to_bind, it must call context.set_binding + with the binding details. If it can partially bind the port, + it must call context.continue_binding with the network + segments to be used to bind at the next lower level. + + If the binding results are committed after bind_port returns, + they will be seen by all mechanism drivers as + update_port_precommit and update_port_postcommit calls. But if + some other thread or process concurrently binds or updates the + port, these binding results will not be committed, and + update_port_precommit and update_port_postcommit will not be + called on the mechanism drivers with these results. Because + binding results can be discarded rather than committed, + drivers should avoid making persistent state changes in + bind_port, or else must ensure that such state changes are + eventually cleaned up. + + Implementing this method explicitly declares the mechanism + driver as having the intention to bind ports. This is inspected + by the QoS service to identify the available QoS rules you + can use with ports. + """ + pass + + @property + def _supports_port_binding(self): + return self.__class__.bind_port != MechanismDriver.bind_port + + def check_vlan_transparency(self, context): + """Check if the network supports vlan transparency. + + :param context: NetworkContext instance describing the network. + + Check if the network supports vlan transparency or not. + """ + pass + + def get_workers(self): + """Get any NeutronWorker instances that should have their own process + + Any driver that needs to run processes separate from the API or RPC + workers, can return a sequence of NeutronWorker instances. + """ + return () + + @classmethod + def is_host_filtering_supported(cls): + return (cls.filter_hosts_with_segment_access != + MechanismDriver.filter_hosts_with_segment_access) + + def filter_hosts_with_segment_access( + self, context, segments, candidate_hosts, agent_getter): + """Filter hosts with access to at least one segment. + + :returns: a set with a subset of candidate_hosts. + + A driver can overload this method to return a subset of candidate_hosts + with the ones with access to at least one segment. + + Default implementation returns all hosts to disable filtering + (backward compatibility). + """ + return candidate_hosts diff --git a/neutron_lib/tests/unit/plugins/ml2/__init__.py b/neutron_lib/tests/unit/plugins/ml2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/neutron_lib/tests/unit/plugins/ml2/test_api.py b/neutron_lib/tests/unit/plugins/ml2/test_api.py new file mode 100644 index 0000000..f4c4d7e --- /dev/null +++ b/neutron_lib/tests/unit/plugins/ml2/test_api.py @@ -0,0 +1,39 @@ +# 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_lib.plugins.ml2 import api +from neutron_lib.tests import _base as base + + +class _MechanismDriver(api.MechanismDriver): + bind_port = lambda s, c: c + + def initialize(self): + pass + + +class TestMechanismDriver(base.BaseTestCase): + + def test__supports_port_binding(self): + self.assertTrue(_MechanismDriver()._supports_port_binding) + + def test_get_workers(self): + self.assertEqual((), _MechanismDriver().get_workers()) + + def test_filter_hosts_with_segment_access(self): + dummy_token = ["X"] + self.assertEqual( + dummy_token, + _MechanismDriver().filter_hosts_with_segment_access( + dummy_token, dummy_token, dummy_token, dummy_token)) diff --git a/releasenotes/notes/rehome-ml2-mechdriver-cc86d3a2fe4c2822.yaml b/releasenotes/notes/rehome-ml2-mechdriver-cc86d3a2fe4c2822.yaml new file mode 100644 index 0000000..e129554 --- /dev/null +++ b/releasenotes/notes/rehome-ml2-mechdriver-cc86d3a2fe4c2822.yaml @@ -0,0 +1,4 @@ +--- +features: + - The ML2 ``MechanismDriver`` class from ``neutron.plugins.ml2.driver_api`` + is now available in ``neutron_lib.plugins.ml2.api``.