subnet calls of ml2 mechanism driver
Implements blueprint ml2-mechanism-driver-subnet-calls Change-Id: Ib9a8009975959692f46f80fb2a850fcc2b22debe
This commit is contained in:
parent
19c29cd27c
commit
49aaf280e1
@ -164,6 +164,38 @@ class NetworkContext(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SubnetContext(object):
|
||||||
|
"""Context passed to MechanismDrivers for changes to subnet resources.
|
||||||
|
|
||||||
|
A SubnetContext instance wraps a subnet resource. It provides
|
||||||
|
helper methods for accessing other relevant information. Results
|
||||||
|
from expensive operations are cached so that other
|
||||||
|
MechanismDrivers can freely access the same information.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def current(self):
|
||||||
|
"""Return the current state of the subnet.
|
||||||
|
|
||||||
|
Return the current state of the subnet, as defined by
|
||||||
|
NeutronPluginBaseV2.create_subnet and all extensions in the
|
||||||
|
ml2 plugin.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractproperty
|
||||||
|
def original(self):
|
||||||
|
"""Return the original state of the subnet.
|
||||||
|
|
||||||
|
Return the original state of the subnet, prior to a call to
|
||||||
|
update_subnet. Method is only valid within calls to
|
||||||
|
update_subnet_precommit and update_subnet_postcommit.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PortContext(object):
|
class PortContext(object):
|
||||||
"""Context passed to MechanismDrivers for changes to port resources.
|
"""Context passed to MechanismDrivers for changes to port resources.
|
||||||
|
|
||||||
@ -222,8 +254,6 @@ class MechanismDriver(object):
|
|||||||
methods that are part of the database transaction.
|
methods that are part of the database transaction.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO(apech): add calls for subnets
|
|
||||||
|
|
||||||
__metaclass__ = ABCMeta
|
__metaclass__ = ABCMeta
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@ -326,6 +356,96 @@ class MechanismDriver(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
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):
|
def create_port_precommit(self, context):
|
||||||
"""Allocate resources for a new port.
|
"""Allocate resources for a new port.
|
||||||
|
|
||||||
|
@ -35,12 +35,15 @@ class NetworkContext(MechanismDriverContext, api.NetworkContext):
|
|||||||
self._original_network = original_network
|
self._original_network = original_network
|
||||||
self._segments = segments
|
self._segments = segments
|
||||||
|
|
||||||
|
@property
|
||||||
def current(self):
|
def current(self):
|
||||||
return self._network
|
return self._network
|
||||||
|
|
||||||
|
@property
|
||||||
def original(self):
|
def original(self):
|
||||||
return self._original_network
|
return self._original_network
|
||||||
|
|
||||||
|
@property
|
||||||
def network_segments(self):
|
def network_segments(self):
|
||||||
if not self._segments:
|
if not self._segments:
|
||||||
self._segments = self._plugin.get_network_segments(
|
self._segments = self._plugin.get_network_segments(
|
||||||
@ -48,6 +51,22 @@ class NetworkContext(MechanismDriverContext, api.NetworkContext):
|
|||||||
return self._segments
|
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):
|
class PortContext(MechanismDriverContext, api.PortContext):
|
||||||
|
|
||||||
def __init__(self, plugin, plugin_context, port,
|
def __init__(self, plugin, plugin_context, port,
|
||||||
@ -57,12 +76,15 @@ class PortContext(MechanismDriverContext, api.PortContext):
|
|||||||
self._original_port = original_port
|
self._original_port = original_port
|
||||||
self._network_context = None
|
self._network_context = None
|
||||||
|
|
||||||
|
@property
|
||||||
def current(self):
|
def current(self):
|
||||||
return self._port
|
return self._port
|
||||||
|
|
||||||
|
@property
|
||||||
def original(self):
|
def original(self):
|
||||||
return self._original_port
|
return self._original_port
|
||||||
|
|
||||||
|
@property
|
||||||
def network(self):
|
def network(self):
|
||||||
"""Return the NetworkContext associated with this port."""
|
"""Return the NetworkContext associated with this port."""
|
||||||
if not self._network_context:
|
if not self._network_context:
|
||||||
|
@ -270,6 +270,92 @@ class MechanismManager(stevedore.named.NamedExtensionManager):
|
|||||||
self._call_on_drivers("delete_network_postcommit", context,
|
self._call_on_drivers("delete_network_postcommit", context,
|
||||||
continue_on_failure=True)
|
continue_on_failure=True)
|
||||||
|
|
||||||
|
def create_subnet_precommit(self, context):
|
||||||
|
"""Notify all mechanism drivers of a subnet creation.
|
||||||
|
|
||||||
|
:raises: neutron.plugins.ml2.common.MechanismDriverError
|
||||||
|
if any mechanism driver create_subnet_precommit call fails.
|
||||||
|
|
||||||
|
Called within the database transaction. If a mechanism driver
|
||||||
|
raises an exception, then a MechanismDriverError is propogated
|
||||||
|
to the caller, triggering a rollback. There is no guarantee
|
||||||
|
that all mechanism drivers are called in this case.
|
||||||
|
"""
|
||||||
|
self._call_on_drivers("create_subnet_precommit", context)
|
||||||
|
|
||||||
|
def create_subnet_postcommit(self, context):
|
||||||
|
"""Notify all mechanism drivers of subnet creation.
|
||||||
|
|
||||||
|
:raises: neutron.plugins.ml2.common.MechanismDriverError
|
||||||
|
if any mechanism driver create_subnet_postcommit call fails.
|
||||||
|
|
||||||
|
Called after the database transaction. If a mechanism driver
|
||||||
|
raises an exception, then a MechanismDriverError is propagated
|
||||||
|
to the caller, where the subnet will be deleted, triggering
|
||||||
|
any required cleanup. There is no guarantee that all mechanism
|
||||||
|
drivers are called in this case.
|
||||||
|
"""
|
||||||
|
self._call_on_drivers("create_subnet_postcommit", context)
|
||||||
|
|
||||||
|
def update_subnet_precommit(self, context):
|
||||||
|
"""Notify all mechanism drivers of a subnet update.
|
||||||
|
|
||||||
|
:raises: neutron.plugins.ml2.common.MechanismDriverError
|
||||||
|
if any mechanism driver update_subnet_precommit call fails.
|
||||||
|
|
||||||
|
Called within the database transaction. If a mechanism driver
|
||||||
|
raises an exception, then a MechanismDriverError is propogated
|
||||||
|
to the caller, triggering a rollback. There is no guarantee
|
||||||
|
that all mechanism drivers are called in this case.
|
||||||
|
"""
|
||||||
|
self._call_on_drivers("update_subnet_precommit", context)
|
||||||
|
|
||||||
|
def update_subnet_postcommit(self, context):
|
||||||
|
"""Notify all mechanism drivers of a subnet update.
|
||||||
|
|
||||||
|
:raises: neutron.plugins.ml2.common.MechanismDriverError
|
||||||
|
if any mechanism driver update_subnet_postcommit call fails.
|
||||||
|
|
||||||
|
Called after the database transaction. If a mechanism driver
|
||||||
|
raises an exception, then a MechanismDriverError is propagated
|
||||||
|
to the caller, where an error is returned to the user. The
|
||||||
|
user is expected to take the appropriate action, whether by
|
||||||
|
retrying the call or deleting the subnet. There is no
|
||||||
|
guarantee that all mechanism drivers are called in this case.
|
||||||
|
"""
|
||||||
|
self._call_on_drivers("update_subnet_postcommit", context)
|
||||||
|
|
||||||
|
def delete_subnet_precommit(self, context):
|
||||||
|
"""Notify all mechanism drivers of a subnet deletion.
|
||||||
|
|
||||||
|
:raises: neutron.plugins.ml2.common.MechanismDriverError
|
||||||
|
if any mechanism driver delete_subnet_precommit call fails.
|
||||||
|
|
||||||
|
Called within the database transaction. If a mechanism driver
|
||||||
|
raises an exception, then a MechanismDriverError is propogated
|
||||||
|
to the caller, triggering a rollback. There is no guarantee
|
||||||
|
that all mechanism drivers are called in this case.
|
||||||
|
"""
|
||||||
|
self._call_on_drivers("delete_subnet_precommit", context)
|
||||||
|
|
||||||
|
def delete_subnet_postcommit(self, context):
|
||||||
|
"""Notify all mechanism drivers of a subnet deletion.
|
||||||
|
|
||||||
|
:raises: neutron.plugins.ml2.common.MechanismDriverError
|
||||||
|
if any mechanism driver delete_subnet_postcommit call fails.
|
||||||
|
|
||||||
|
Called after the database transaction. If any mechanism driver
|
||||||
|
raises an error, then the error is logged but we continue to
|
||||||
|
call every other mechanism driver. A MechanismDriverError is
|
||||||
|
then reraised at the end to notify the caller of a failure. In
|
||||||
|
general we expect the caller to ignore the error, as the
|
||||||
|
subnet resource has already been deleted from the database
|
||||||
|
and it doesn't make sense to undo the action by recreating the
|
||||||
|
subnet.
|
||||||
|
"""
|
||||||
|
self._call_on_drivers("delete_subnet_postcommit", context,
|
||||||
|
continue_on_failure=True)
|
||||||
|
|
||||||
def create_port_precommit(self, context):
|
def create_port_precommit(self, context):
|
||||||
"""Notify all mechanism drivers of a port creation.
|
"""Notify all mechanism drivers of a port creation.
|
||||||
|
|
||||||
|
@ -311,6 +311,54 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
pass
|
pass
|
||||||
self.notifier.network_delete(context, id)
|
self.notifier.network_delete(context, id)
|
||||||
|
|
||||||
|
def create_subnet(self, context, subnet):
|
||||||
|
session = context.session
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
result = super(Ml2Plugin, self).create_subnet(context, subnet)
|
||||||
|
mech_context = driver_context.SubnetContext(self, context, result)
|
||||||
|
self.mechanism_manager.create_subnet_precommit(mech_context)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.mechanism_manager.create_subnet_postcommit(mech_context)
|
||||||
|
except ml2_exc.MechanismDriverError:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.error(_("mechanism_manager.create_subnet failed, "
|
||||||
|
"deleting subnet '%s'"), result['id'])
|
||||||
|
self.delete_subnet(context, result['id'])
|
||||||
|
return result
|
||||||
|
|
||||||
|
def update_subnet(self, context, id, subnet):
|
||||||
|
session = context.session
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
original_subnet = super(Ml2Plugin, self).get_subnet(context, id)
|
||||||
|
updated_subnet = super(Ml2Plugin, self).update_subnet(
|
||||||
|
context, id, subnet)
|
||||||
|
mech_context = driver_context.SubnetContext(
|
||||||
|
self, context, updated_subnet, original_subnet=original_subnet)
|
||||||
|
self.mechanism_manager.update_subnet_precommit(mech_context)
|
||||||
|
|
||||||
|
# TODO(apech) - handle errors raised by update_subnet, potentially
|
||||||
|
# by re-calling update_subnet with the previous attributes. For
|
||||||
|
# now the error is propogated to the caller, which is expected to
|
||||||
|
# either undo/retry the operation or delete the resource.
|
||||||
|
self.mechanism_manager.update_subnet_postcommit(mech_context)
|
||||||
|
return updated_subnet
|
||||||
|
|
||||||
|
def delete_subnet(self, context, id):
|
||||||
|
session = context.session
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
subnet = self.get_subnet(context, id)
|
||||||
|
mech_context = driver_context.SubnetContext(self, context, subnet)
|
||||||
|
self.mechanism_manager.delete_subnet_precommit(mech_context)
|
||||||
|
super(Ml2Plugin, self).delete_subnet(context, id)
|
||||||
|
try:
|
||||||
|
self.mechanism_manager.delete_subnet_postcommit(mech_context)
|
||||||
|
except ml2_exc.MechanismDriverError:
|
||||||
|
# TODO(apech) - One or more mechanism driver failed to
|
||||||
|
# delete the subnet. Ideally we'd notify the caller of
|
||||||
|
# the fact that an error occurred.
|
||||||
|
pass
|
||||||
|
|
||||||
def create_port(self, context, port):
|
def create_port(self, context, port):
|
||||||
attrs = port['port']
|
attrs = port['port']
|
||||||
attrs['status'] = const.PORT_STATUS_DOWN
|
attrs['status'] = const.PORT_STATUS_DOWN
|
||||||
|
@ -33,9 +33,9 @@ class LoggerMechanismDriver(api.MechanismDriver):
|
|||||||
"(original settings %(original)s) and "
|
"(original settings %(original)s) and "
|
||||||
"network segments %(segments)s"),
|
"network segments %(segments)s"),
|
||||||
{'method': method_name,
|
{'method': method_name,
|
||||||
'current': context.current(),
|
'current': context.current,
|
||||||
'original': context.original(),
|
'original': context.original,
|
||||||
'segments': context.network_segments()})
|
'segments': context.network_segments})
|
||||||
|
|
||||||
def create_network_precommit(self, context):
|
def create_network_precommit(self, context):
|
||||||
self._log_network_call("create_network_precommit", context)
|
self._log_network_call("create_network_precommit", context)
|
||||||
@ -55,14 +55,39 @@ class LoggerMechanismDriver(api.MechanismDriver):
|
|||||||
def delete_network_postcommit(self, context):
|
def delete_network_postcommit(self, context):
|
||||||
self._log_network_call("delete_network_postcommit", context)
|
self._log_network_call("delete_network_postcommit", context)
|
||||||
|
|
||||||
|
def _log_subnet_call(self, method_name, context):
|
||||||
|
LOG.info(_("%(method)s called with subnet settings %(current)s "
|
||||||
|
"(original settings %(original)s)"),
|
||||||
|
{'method': method_name,
|
||||||
|
'current': context.current,
|
||||||
|
'original': context.original})
|
||||||
|
|
||||||
|
def create_subnet_precommit(self, context):
|
||||||
|
self._log_subnet_call("create_subnet_precommit", context)
|
||||||
|
|
||||||
|
def create_subnet_postcommit(self, context):
|
||||||
|
self._log_subnet_call("create_subnet_postcommit", context)
|
||||||
|
|
||||||
|
def update_subnet_precommit(self, context):
|
||||||
|
self._log_subnet_call("update_subnet_precommit", context)
|
||||||
|
|
||||||
|
def update_subnet_postcommit(self, context):
|
||||||
|
self._log_subnet_call("update_subnet_postcommit", context)
|
||||||
|
|
||||||
|
def delete_subnet_precommit(self, context):
|
||||||
|
self._log_subnet_call("delete_subnet_precommit", context)
|
||||||
|
|
||||||
|
def delete_subnet_postcommit(self, context):
|
||||||
|
self._log_subnet_call("delete_subnet_postcommit", context)
|
||||||
|
|
||||||
def _log_port_call(self, method_name, context):
|
def _log_port_call(self, method_name, context):
|
||||||
network_context = context.network()
|
network_context = context.network
|
||||||
LOG.info(_("%(method)s called with port settings %(current)s "
|
LOG.info(_("%(method)s called with port settings %(current)s "
|
||||||
"(original settings %(original)s) on network %(network)s"),
|
"(original settings %(original)s) on network %(network)s"),
|
||||||
{'method': method_name,
|
{'method': method_name,
|
||||||
'current': context.current(),
|
'current': context.current,
|
||||||
'original': context.original(),
|
'original': context.original,
|
||||||
'network': network_context.current()})
|
'network': network_context.current})
|
||||||
|
|
||||||
def create_port_precommit(self, context):
|
def create_port_precommit(self, context):
|
||||||
self._log_port_call("create_port_precommit", context)
|
self._log_port_call("create_port_precommit", context)
|
||||||
|
@ -25,12 +25,14 @@ class TestMechanismDriver(api.MechanismDriver):
|
|||||||
|
|
||||||
def _check_network_context(self, context, original_expected):
|
def _check_network_context(self, context, original_expected):
|
||||||
assert(isinstance(context, driver_context.NetworkContext))
|
assert(isinstance(context, driver_context.NetworkContext))
|
||||||
assert(context.current())
|
assert(isinstance(context.current, dict))
|
||||||
|
assert(context.current['id'] is not None)
|
||||||
if original_expected:
|
if original_expected:
|
||||||
assert(context.original())
|
assert(isinstance(context.original, dict))
|
||||||
|
assert(context.current['id'] == context.original['id'])
|
||||||
else:
|
else:
|
||||||
assert(not context.original())
|
assert(not context.original)
|
||||||
assert(context.network_segments())
|
assert(context.network_segments)
|
||||||
|
|
||||||
def create_network_precommit(self, context):
|
def create_network_precommit(self, context):
|
||||||
self._check_network_context(context, False)
|
self._check_network_context(context, False)
|
||||||
@ -50,15 +52,45 @@ class TestMechanismDriver(api.MechanismDriver):
|
|||||||
def delete_network_postcommit(self, context):
|
def delete_network_postcommit(self, context):
|
||||||
self._check_network_context(context, False)
|
self._check_network_context(context, False)
|
||||||
|
|
||||||
|
def _check_subnet_context(self, context, original_expected):
|
||||||
|
assert(isinstance(context, driver_context.SubnetContext))
|
||||||
|
assert(isinstance(context.current, dict))
|
||||||
|
assert(context.current['id'] is not None)
|
||||||
|
if original_expected:
|
||||||
|
assert(isinstance(context.original, dict))
|
||||||
|
assert(context.current['id'] == context.original['id'])
|
||||||
|
else:
|
||||||
|
assert(not context.original)
|
||||||
|
|
||||||
|
def create_subnet_precommit(self, context):
|
||||||
|
self._check_subnet_context(context, False)
|
||||||
|
|
||||||
|
def create_subnet_postcommit(self, context):
|
||||||
|
self._check_subnet_context(context, False)
|
||||||
|
|
||||||
|
def update_subnet_precommit(self, context):
|
||||||
|
self._check_subnet_context(context, True)
|
||||||
|
|
||||||
|
def update_subnet_postcommit(self, context):
|
||||||
|
self._check_subnet_context(context, True)
|
||||||
|
|
||||||
|
def delete_subnet_precommit(self, context):
|
||||||
|
self._check_subnet_context(context, False)
|
||||||
|
|
||||||
|
def delete_subnet_postcommit(self, context):
|
||||||
|
self._check_subnet_context(context, False)
|
||||||
|
|
||||||
def _check_port_context(self, context, original_expected):
|
def _check_port_context(self, context, original_expected):
|
||||||
assert(isinstance(context, driver_context.PortContext))
|
assert(isinstance(context, driver_context.PortContext))
|
||||||
assert(context.current())
|
assert(isinstance(context.current, dict))
|
||||||
|
assert(context.current['id'] is not None)
|
||||||
if original_expected:
|
if original_expected:
|
||||||
assert(context.original())
|
assert(isinstance(context.original, dict))
|
||||||
|
assert(context.current['id'] == context.original['id'])
|
||||||
else:
|
else:
|
||||||
assert(not context.original())
|
assert(not context.original)
|
||||||
network_context = context.network()
|
network_context = context.network
|
||||||
assert(network_context)
|
assert(isinstance(network_context, driver_context.NetworkContext))
|
||||||
self._check_network_context(network_context, False)
|
self._check_network_context(network_context, False)
|
||||||
|
|
||||||
def create_port_precommit(self, context):
|
def create_port_precommit(self, context):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user