Passes the plugin context variable in the ML2 Extension Driver API

Many neutron extensions(like portsecurity) use the plugin_context
variable instead of just the database session. This change
modifies the extension driver api to pass the plugin_context

Change request also modifies the extend_XXX resource api to use the
respective data model(network/subnet/port) passed to it.

Implements: blueprint extensions-in-ml2
Partially Implements: blueprint ml2-ovs-portsecurity
Closes-Bug: 1382448
Change-Id: Icf84615e5fee8b59cbc95ab9b634f1a49f4b56a3
This commit is contained in:
Shweta P 2015-02-03 20:23:31 -05:00 committed by Yalei Wang
parent 10b3a5bc90
commit c027c6cef8
4 changed files with 136 additions and 68 deletions

View File

@ -831,94 +831,95 @@ class ExtensionDriver(object):
""" """
pass pass
def process_create_network(self, session, data, result): def process_create_network(self, plugin_context, data, result):
"""Process extended attributes for create network. """Process extended attributes for create network.
:param session: database session :param plugin_context: plugin request context
:param data: dictionary of incoming network data :param data: dictionary of incoming network data
:param result: network dictionary to extend :param result: network dictionary to extend
Called inside transaction context on session to validate and Called inside transaction context on plugin_context.session to
persist any extended network attributes defined by this validate and persist any extended network attributes defined by this
driver. Extended attribute values must also be added to driver. Extended attribute values must also be added to
result. result.
""" """
pass pass
def process_create_subnet(self, session, data, result): def process_create_subnet(self, plugin_context, data, result):
"""Process extended attributes for create subnet. """Process extended attributes for create subnet.
:param session: database session :param plugin_context: plugin request context
:param data: dictionary of incoming subnet data :param data: dictionary of incoming subnet data
:param result: subnet dictionary to extend :param result: subnet dictionary to extend
Called inside transaction context on session to validate and Called inside transaction context on plugin_context.session to
persist any extended subnet attributes defined by this validate and persist any extended subnet attributes defined by this
driver. Extended attribute values must also be added to driver. Extended attribute values must also be added to
result. result.
""" """
pass pass
def process_create_port(self, session, data, result): def process_create_port(self, plugin_context, data, result):
"""Process extended attributes for create port. """Process extended attributes for create port.
:param session: database session :param plugin_context: plugin request context
:param data: dictionary of incoming port data :param data: dictionary of incoming port data
:param result: port dictionary to extend :param result: port dictionary to extend
Called inside transaction context on session to validate and Called inside transaction context on plugin_context.session to
persist any extended port attributes defined by this validate and persist any extended port attributes defined by this
driver. Extended attribute values must also be added to driver. Extended attribute values must also be added to
result. result.
""" """
pass pass
def process_update_network(self, session, data, result): def process_update_network(self, plugin_context, data, result):
"""Process extended attributes for update network. """Process extended attributes for update network.
:param session: database session :param plugin_context: plugin request context
:param data: dictionary of incoming network data :param data: dictionary of incoming network data
:param result: network dictionary to extend :param result: network dictionary to extend
Called inside transaction context on session to validate and Called inside transaction context on plugin_context.session to
update any extended network attributes defined by this validate and update any extended network attributes defined by this
driver. Extended attribute values, whether updated or not, driver. Extended attribute values, whether updated or not,
must also be added to result. must also be added to result.
""" """
pass pass
def process_update_subnet(self, session, data, result): def process_update_subnet(self, plugin_context, data, result):
"""Process extended attributes for update subnet. """Process extended attributes for update subnet.
:param session: database session :param plugin_context: plugin request context
:param data: dictionary of incoming subnet data :param data: dictionary of incoming subnet data
:param result: subnet dictionary to extend :param result: subnet dictionary to extend
Called inside transaction context on session to validate and Called inside transaction context on plugin_context.session to
update any extended subnet attributes defined by this validate and update any extended subnet attributes defined by this
driver. Extended attribute values, whether updated or not, driver. Extended attribute values, whether updated or not,
must also be added to result. must also be added to result.
""" """
pass pass
def process_update_port(self, session, data, result): def process_update_port(self, plugin_context, data, result):
"""Process extended attributes for update port. """Process extended attributes for update port.
:param session: database session :param plugin_context: plugin request context
:param data: dictionary of incoming port data :param data: dictionary of incoming port data
:param result: port dictionary to extend :param result: port dictionary to extend
Called inside transaction context on session to validate and Called inside transaction context on plugin_context.session to
update any extended port attributes defined by this validate and update any extended port attributes defined by this
driver. Extended attribute values, whether updated or not, driver. Extended attribute values, whether updated or not,
must also be added to result. must also be added to result.
""" """
pass pass
def extend_network_dict(self, session, result): def extend_network_dict(self, session, base_model, result):
"""Add extended attributes to network dictionary. """Add extended attributes to network dictionary.
:param session: database session :param session: database session
:param base_model: network model data
:param result: network dictionary to extend :param result: network dictionary to extend
Called inside transaction context on session to add any Called inside transaction context on session to add any
@ -928,10 +929,11 @@ class ExtensionDriver(object):
""" """
pass pass
def extend_subnet_dict(self, session, result): def extend_subnet_dict(self, session, base_model, result):
"""Add extended attributes to subnet dictionary. """Add extended attributes to subnet dictionary.
:param session: database session :param session: database session
:param base_model: subnet model data
:param result: subnet dictionary to extend :param result: subnet dictionary to extend
Called inside transaction context on session to add any Called inside transaction context on session to add any
@ -941,15 +943,16 @@ class ExtensionDriver(object):
""" """
pass pass
def extend_port_dict(self, session, result): def extend_port_dict(self, session, base_model, result):
"""Add extended attributes to port dictionary. """Add extended attributes to port dictionary.
:param session: database session :param session: database session
:param base_model: port model data
:param result: port dictionary to extend :param result: port dictionary to extend
Called inside transaction context on session to add any Called inside transaction context on session to add any
extended attributes defined by this driver to a port extended attributes defined by this driver to a port
dictionary to be used for mechanism driver calls and/or dictionary to be used for mechanism driver calls
returned as the result of a port operation. and/or returned as the result of a port operation.
""" """
pass pass

View File

@ -685,62 +685,64 @@ class ExtensionManager(stevedore.named.NamedExtensionManager):
{'alias': alias, 'drv': driver.name}) {'alias': alias, 'drv': driver.name})
return exts return exts
def _call_on_ext_drivers(self, method_name, session, data, result): def _call_on_ext_drivers(self, method_name, plugin_context, data, result):
"""Helper method for calling a method across all extension drivers.""" """Helper method for calling a method across all extension drivers."""
for driver in self.ordered_ext_drivers: for driver in self.ordered_ext_drivers:
try: try:
getattr(driver.obj, method_name)(session, data, result) getattr(driver.obj, method_name)(plugin_context, data, result)
except Exception: except Exception:
LOG.exception( LOG.exception(
_LE("Extension driver '%(name)s' failed in %(method)s"), _LE("Extension driver '%(name)s' failed in %(method)s"),
{'name': driver.name, 'method': method_name} {'name': driver.name, 'method': method_name}
) )
def process_create_network(self, session, data, result): def process_create_network(self, plugin_context, data, result):
"""Notify all extension drivers during network creation.""" """Notify all extension drivers during network creation."""
self._call_on_ext_drivers("process_create_network", session, data, self._call_on_ext_drivers("process_create_network", plugin_context,
result) data, result)
def process_update_network(self, session, data, result): def process_update_network(self, plugin_context, data, result):
"""Notify all extension drivers during network update.""" """Notify all extension drivers during network update."""
self._call_on_ext_drivers("process_update_network", session, data, self._call_on_ext_drivers("process_update_network", plugin_context,
result) data, result)
def process_create_subnet(self, session, data, result): def process_create_subnet(self, plugin_context, data, result):
"""Notify all extension drivers during subnet creation.""" """Notify all extension drivers during subnet creation."""
self._call_on_ext_drivers("process_create_subnet", session, data, self._call_on_ext_drivers("process_create_subnet", plugin_context,
result) data, result)
def process_update_subnet(self, session, data, result): def process_update_subnet(self, plugin_context, data, result):
"""Notify all extension drivers during subnet update.""" """Notify all extension drivers during subnet update."""
self._call_on_ext_drivers("process_update_subnet", session, data, self._call_on_ext_drivers("process_update_subnet", plugin_context,
result) data, result)
def process_create_port(self, session, data, result): def process_create_port(self, plugin_context, data, result):
"""Notify all extension drivers during port creation.""" """Notify all extension drivers during port creation."""
self._call_on_ext_drivers("process_create_port", session, data, result) self._call_on_ext_drivers("process_create_port", plugin_context,
data, result)
def process_update_port(self, session, data, result): def process_update_port(self, plugin_context, data, result):
"""Notify all extension drivers during port update.""" """Notify all extension drivers during port update."""
self._call_on_ext_drivers("process_update_port", session, data, result) self._call_on_ext_drivers("process_update_port", plugin_context,
data, result)
def extend_network_dict(self, session, result): def extend_network_dict(self, session, base_model, result):
"""Notify all extension drivers to extend network dictionary.""" """Notify all extension drivers to extend network dictionary."""
for driver in self.ordered_ext_drivers: for driver in self.ordered_ext_drivers:
driver.obj.extend_network_dict(session, result) driver.obj.extend_network_dict(session, base_model, result)
LOG.info(_LI("Extended network dict for driver '%(drv)s'"), LOG.info(_LI("Extended network dict for driver '%(drv)s'"),
{'drv': driver.name}) {'drv': driver.name})
def extend_subnet_dict(self, session, result): def extend_subnet_dict(self, session, base_model, result):
"""Notify all extension drivers to extend subnet dictionary.""" """Notify all extension drivers to extend subnet dictionary."""
for driver in self.ordered_ext_drivers: for driver in self.ordered_ext_drivers:
driver.obj.extend_subnet_dict(session, result) driver.obj.extend_subnet_dict(session, base_model, result)
LOG.info(_LI("Extended subnet dict for driver '%(drv)s'"), LOG.info(_LI("Extended subnet dict for driver '%(drv)s'"),
{'drv': driver.name}) {'drv': driver.name})
def extend_port_dict(self, session, result): def extend_port_dict(self, session, base_model, result):
"""Notify all extension drivers to extend port dictionary.""" """Notify all extension drivers to extend port dictionary."""
for driver in self.ordered_ext_drivers: for driver in self.ordered_ext_drivers:
driver.obj.extend_port_dict(session, result) driver.obj.extend_port_dict(session, base_model, result)
LOG.info(_LI("Extended port dict for driver '%(drv)s'"), LOG.info(_LI("Extended port dict for driver '%(drv)s'"),
{'drv': driver.name}) {'drv': driver.name})

View File

@ -477,17 +477,18 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
def _ml2_md_extend_network_dict(self, result, netdb): def _ml2_md_extend_network_dict(self, result, netdb):
session = db_api.get_session() session = db_api.get_session()
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
self.extension_manager.extend_network_dict(session, result) self.extension_manager.extend_network_dict(session, netdb, result)
def _ml2_md_extend_port_dict(self, result, portdb): def _ml2_md_extend_port_dict(self, result, portdb):
session = db_api.get_session() session = db_api.get_session()
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
self.extension_manager.extend_port_dict(session, result) self.extension_manager.extend_port_dict(session, portdb, result)
def _ml2_md_extend_subnet_dict(self, result, subnetdb): def _ml2_md_extend_subnet_dict(self, result, subnetdb):
session = db_api.get_session() session = db_api.get_session()
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
self.extension_manager.extend_subnet_dict(session, result) self.extension_manager.extend_subnet_dict(
session, subnetdb, result)
# Note - The following hook methods have "ml2" in their names so # Note - The following hook methods have "ml2" in their names so
# that they are not called twice during unit tests due to global # that they are not called twice during unit tests due to global
@ -587,7 +588,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
self._ensure_default_security_group(context, tenant_id) self._ensure_default_security_group(context, tenant_id)
result = super(Ml2Plugin, self).create_network(context, network) result = super(Ml2Plugin, self).create_network(context, network)
self.extension_manager.process_create_network(session, net_data, self.extension_manager.process_create_network(context, net_data,
result) result)
self._process_l3_create(context, result, net_data) self._process_l3_create(context, result, net_data)
net_data['id'] = result['id'] net_data['id'] = result['id']
@ -624,8 +625,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
updated_network = super(Ml2Plugin, self).update_network(context, updated_network = super(Ml2Plugin, self).update_network(context,
id, id,
network) network)
self.extension_manager.process_update_network(session, network, self.extension_manager.process_update_network(context, network,
original_network) updated_network)
self._process_l3_update(context, updated_network, self._process_l3_update(context, updated_network,
network['network']) network['network'])
self.type_manager.extend_network_dict_provider(context, self.type_manager.extend_network_dict_provider(context,
@ -777,7 +778,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
session = context.session session = context.session
with session.begin(subtransactions=True): with session.begin(subtransactions=True):
result = super(Ml2Plugin, self).create_subnet(context, subnet) result = super(Ml2Plugin, self).create_subnet(context, subnet)
self.extension_manager.process_create_subnet(session, subnet, self.extension_manager.process_create_subnet(context, subnet,
result) result)
mech_context = driver_context.SubnetContext(self, context, result) mech_context = driver_context.SubnetContext(self, context, result)
self.mechanism_manager.create_subnet_precommit(mech_context) self.mechanism_manager.create_subnet_precommit(mech_context)
@ -805,8 +806,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
original_subnet = super(Ml2Plugin, self).get_subnet(context, id) original_subnet = super(Ml2Plugin, self).get_subnet(context, id)
updated_subnet = super(Ml2Plugin, self).update_subnet( updated_subnet = super(Ml2Plugin, self).update_subnet(
context, id, subnet) context, id, subnet)
self.extension_manager.process_update_subnet(session, subnet, self.extension_manager.process_update_subnet(context, subnet,
original_subnet) updated_subnet)
mech_context = driver_context.SubnetContext( mech_context = driver_context.SubnetContext(
self, context, updated_subnet, original_subnet=original_subnet) self, context, updated_subnet, original_subnet=original_subnet)
self.mechanism_manager.update_subnet_precommit(mech_context) self.mechanism_manager.update_subnet_precommit(mech_context)
@ -913,7 +914,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
sgids = self._get_security_groups_on_port(context, port) sgids = self._get_security_groups_on_port(context, port)
dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, []) dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])
result = super(Ml2Plugin, self).create_port(context, port) result = super(Ml2Plugin, self).create_port(context, port)
self.extension_manager.process_create_port(session, attrs, result) self.extension_manager.process_create_port(context, attrs, result)
self._process_port_create_security_group(context, result, sgids) self._process_port_create_security_group(context, result, sgids)
network = self.get_network(context, result['network_id']) network = self.get_network(context, result['network_id'])
binding = db.add_port_binding(session, result['id']) binding = db.add_port_binding(session, result['id'])
@ -1011,8 +1012,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
original_port = self._make_port_dict(port_db) original_port = self._make_port_dict(port_db)
updated_port = super(Ml2Plugin, self).update_port(context, id, updated_port = super(Ml2Plugin, self).update_port(context, id,
port) port)
self.extension_manager.process_update_port(session, attrs, self.extension_manager.process_update_port(context, attrs,
original_port) updated_port)
if addr_pair.ADDRESS_PAIRS in port['port']: if addr_pair.ADDRESS_PAIRS in port['port']:
need_port_update_notify |= ( need_port_update_notify |= (
self.update_address_pairs_on_port(context, id, port, self.update_address_pairs_on_port(context, id, port,

View File

@ -29,19 +29,57 @@ class ExtensionDriverTestCase(test_ml2_plugin.Ml2PluginV2TestCase):
def test_network_attr(self): def test_network_attr(self):
with self.network() as network: with self.network() as network:
# Test create network
ent = network['network'].get('network_extension') ent = network['network'].get('network_extension')
self.assertIsNotNone(ent) self.assertIsNotNone(ent)
# Test list networks
res = self._list('networks')
val = res['networks'][0].get('network_extension')
self.assertEqual('Test_Network_Extension', val)
# Test network update
data = {'network':
{'network_extension': 'Test_Network_Extension_Update'}}
res = self._update('networks', network['network']['id'], data)
val = res['network'].get('network_extension')
self.assertEqual('Test_Network_Extension_Update', val)
def test_subnet_attr(self): def test_subnet_attr(self):
with self.subnet() as subnet: with self.subnet() as subnet:
# Test create subnet
ent = subnet['subnet'].get('subnet_extension') ent = subnet['subnet'].get('subnet_extension')
self.assertIsNotNone(ent) self.assertIsNotNone(ent)
# Test list subnets
res = self._list('subnets')
val = res['subnets'][0].get('subnet_extension')
self.assertEqual('Test_Subnet_Extension', val)
# Test subnet update
data = {'subnet':
{'subnet_extension': 'Test_Subnet_Extension_Update'}}
res = self._update('subnets', subnet['subnet']['id'], data)
val = res['subnet'].get('subnet_extension')
self.assertEqual('Test_Subnet_Extension_Update', val)
def test_port_attr(self): def test_port_attr(self):
with self.port() as port: with self.port() as port:
# Test create port
ent = port['port'].get('port_extension') ent = port['port'].get('port_extension')
self.assertIsNotNone(ent) self.assertIsNotNone(ent)
# Test list ports
res = self._list('ports')
val = res['ports'][0].get('port_extension')
self.assertEqual('Test_Port_Extension', val)
# Test port update
data = {'port': {'port_extension': 'Test_Port_Extension_Update'}}
res = self._update('ports', port['port']['id'], data)
val = res['port'].get('port_extension')
self.assertEqual('Test_Port_Extension_Update', val)
class TestExtensionDriver(api.ExtensionDriver): class TestExtensionDriver(api.ExtensionDriver):
_supported_extension_alias = 'test_extension' _supported_extension_alias = 'test_extension'
@ -56,11 +94,35 @@ class TestExtensionDriver(api.ExtensionDriver):
def extension_alias(self): def extension_alias(self):
return self._supported_extension_alias return self._supported_extension_alias
def process_create_network(self, session, data, result): def process_create_network(self, plugin_context, data, result):
result['network_extension'] = self.network_extension result['network_extension'] = self.network_extension
def process_create_subnet(self, session, data, result): def process_create_subnet(self, plugin_context, data, result):
result['subnet_extension'] = self.subnet_extension result['subnet_extension'] = self.subnet_extension
def process_create_port(self, session, data, result): def process_create_port(self, plugin_context, data, result):
result['port_extension'] = self.port_extension
def process_update_network(self, plugin_context, data, result):
self.network_extension = data['network']['network_extension']
result['network_extension'] = self.network_extension
def process_update_subnet(self, plugin_context, data, result):
self.subnet_extension = data['subnet']['subnet_extension']
result['subnet_extension'] = self.subnet_extension
def process_update_port(self, plugin_context, data, result):
self.port_extension = data['port_extension']
result['port_extension'] = self.port_extension
def extend_network_dict(self, session, base_model, result):
if self._supported_extension_alias is 'test_extension':
result['network_extension'] = self.network_extension
def extend_subnet_dict(self, session, base_model, result):
if self._supported_extension_alias is 'test_extension':
result['subnet_extension'] = self.subnet_extension
def extend_port_dict(self, session, base_model, result):
if self._supported_extension_alias is 'test_extension':
result['port_extension'] = self.port_extension result['port_extension'] = self.port_extension