diff --git a/neutron/agent/rpc.py b/neutron/agent/rpc.py index 732c4cd359a..13a2b7f1ac9 100644 --- a/neutron/agent/rpc.py +++ b/neutron/agent/rpc.py @@ -241,7 +241,7 @@ class CacheBackedPluginApi(PluginApi): mac_addr = str(netaddr.EUI(str(port_obj.mac_address), dialect=netaddr.mac_unix_expanded)) binding = utils.get_port_binding_by_status_and_host( - port_obj.binding, constants.ACTIVE, raise_if_not_found=True, + port_obj.bindings, constants.ACTIVE, raise_if_not_found=True, port_id=port_obj.id) entry = { 'device': device, diff --git a/neutron/db/l3_dvrscheduler_db.py b/neutron/db/l3_dvrscheduler_db.py index e50f5071edd..a974dc786c6 100644 --- a/neutron/db/l3_dvrscheduler_db.py +++ b/neutron/db/l3_dvrscheduler_db.py @@ -284,7 +284,7 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin): query = context.session.query( models_v2.IPAllocation.subnet_id).distinct() query = query.join(models_v2.IPAllocation.port) - query = query.join(models_v2.Port.port_binding) + query = query.join(models_v2.Port.port_bindings) query = query.filter(ml2_models.PortBinding.host == host) owner_filter = or_( models_v2.Port.device_owner.startswith( diff --git a/neutron/objects/ports.py b/neutron/objects/ports.py index 1b422ae9d38..18f275a7c74 100644 --- a/neutron/objects/ports.py +++ b/neutron/objects/ports.py @@ -283,7 +283,7 @@ class Port(base.NeutronDbObject): 'allowed_address_pairs': obj_fields.ListOfObjectsField( 'AllowedAddressPair', nullable=True ), - 'binding': obj_fields.ListOfObjectsField( + 'bindings': obj_fields.ListOfObjectsField( 'PortBinding', nullable=True ), 'data_plane_status': obj_fields.ObjectField( @@ -324,7 +324,7 @@ class Port(base.NeutronDbObject): synthetic_fields = [ 'allowed_address_pairs', - 'binding', + 'bindings', 'binding_levels', 'data_plane_status', 'dhcp_options', @@ -337,7 +337,7 @@ class Port(base.NeutronDbObject): ] fields_need_translation = { - 'binding': 'port_binding', + 'bindings': 'port_bindings', 'dhcp_options': 'dhcp_opts', 'distributed_bindings': 'distributed_port_binding', 'security': 'port_security', @@ -479,10 +479,10 @@ class Port(base.NeutronDbObject): # Previous versions only support one port binding. The following # lines look for the active port binding, which is the only one # needed in previous versions - if 'binding' in primitive: - original_binding = primitive['binding'] + if 'bindings' in primitive: + original_bindings = primitive.pop('bindings') primitive['binding'] = None - for a_binding in original_binding: + for a_binding in original_bindings: if (a_binding['versioned_object.data']['status'] == constants.ACTIVE): primitive['binding'] = a_binding diff --git a/neutron/plugins/ml2/models.py b/neutron/plugins/ml2/models.py index dcc15fcf4f8..e4bf8de3355 100644 --- a/neutron/plugins/ml2/models.py +++ b/neutron/plugins/ml2/models.py @@ -58,9 +58,7 @@ class PortBinding(model_base.BASEV2): port = orm.relationship( models_v2.Port, load_on_pending=True, - # TODO(mlavalle) change name of the relationship to reflect that it is - # now an iterable - backref=orm.backref("port_binding", + backref=orm.backref("port_bindings", lazy='joined', cascade='delete')) revises_on_change = ('port', ) diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index 4a491f7acce..61899152bac 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -117,7 +117,7 @@ def _ml2_port_result_filter_hook(query, filters): if not values: return query bind_criteria = models.PortBinding.host.in_(values) - return query.filter(models_v2.Port.port_binding.any(bind_criteria)) + return query.filter(models_v2.Port.port_bindings.any(bind_criteria)) @resource_extend.has_resource_extenders @@ -247,7 +247,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, port_id = object_id port = db.get_port(context, port_id) port_binding = utils.get_port_binding_by_status_and_host( - getattr(port, 'port_binding', []), const.ACTIVE) + getattr(port, 'port_bindings', []), const.ACTIVE) if not port or not port_binding: LOG.debug("Port %s was deleted so its status cannot be updated.", port_id) @@ -503,7 +503,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, try: port_db = self._get_port(plugin_context, port_id) cur_binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) except exc.PortNotFound: port_db, cur_binding = None, None if not port_db or not cur_binding: @@ -551,7 +551,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, if new_binding.status == const.INACTIVE: cur_context_binding = ( utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.INACTIVE, + port_db.port_bindings, const.INACTIVE, host=new_binding.host)) cur_context = driver_context.PortContext( self, plugin_context, port, network, cur_context_binding, None, @@ -658,7 +658,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, def _ml2_extend_port_dict_binding(port_res, port_db): plugin = directory.get_plugin() port_binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) # None when called during unit tests for other plugins. if port_binding: plugin._update_port_dict_binding(port_res, port_binding) @@ -1332,7 +1332,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, with db_api.context_manager.writer.using(context): port_db = self._get_port(context, id) binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) if not binding: raise exc.PortNotFound(port_id=id) mac_address_updated = self._check_mac_update_allowed( @@ -1551,7 +1551,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, try: port_db = self._get_port(context, id) binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE, + port_db.port_bindings, const.ACTIVE, raise_if_not_found=True, port_id=id) except exc.PortNotFound: LOG.debug("The port '%s' was deleted", id) @@ -1671,7 +1671,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, # concurrent port deletion. # It's not an error condition. binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) if not binding: LOG.info("Binding info for port %s was not found, " "it might have been deleted already.", @@ -1715,7 +1715,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, bindlevelhost_match = host else: binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) bindlevelhost_match = binding.host if binding else None if not binding: LOG.info("Binding info for port %s was not found, " @@ -1801,7 +1801,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, context.session.flush() updated_port = self._make_port_dict(port) binding = utils.get_port_binding_by_status_and_host( - port.port_binding, const.ACTIVE, raise_if_not_found=True, + port.port_bindings, const.ACTIVE, raise_if_not_found=True, port_id=port_id) levels = db.get_binding_levels(context, port.id, binding.host) mech_context = driver_context.PortContext( @@ -2047,14 +2047,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, with db_api.context_manager.writer.using(context): port_db = self._get_port(context, port_id) self._validate_compute_port(port_db) - if self._get_binding_for_host(port_db.port_binding, + if self._get_binding_for_host(port_db.port_bindings, attrs[pbe_ext.HOST]): raise n_exc.PortBindingAlreadyExists( port_id=port_id, host=attrs[pbe_ext.HOST]) status = const.ACTIVE is_active_binding = True active_binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) if active_binding: status = const.INACTIVE is_active_binding = False @@ -2128,8 +2128,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, with db_api.context_manager.writer.using(context): port_db = self._get_port(context, port_id) self._validate_compute_port(port_db) - original_binding = self._get_binding_for_host(port_db.port_binding, - host) + original_binding = self._get_binding_for_host( + port_db.port_bindings, host) if not original_binding: raise n_exc.PortBindingNotFound(port_id=port_id, host=host) is_active_binding = (original_binding.status == const.ACTIVE) @@ -2166,12 +2166,12 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, port_db = self._get_port(context, port_id) self._validate_compute_port(port_db) active_binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.ACTIVE) + port_db.port_bindings, const.ACTIVE) if host == (active_binding and active_binding.host): raise n_exc.PortBindingAlreadyActive(port_id=port_id, host=host) inactive_binding = utils.get_port_binding_by_status_and_host( - port_db.port_binding, const.INACTIVE, host=host) + port_db.port_bindings, const.INACTIVE, host=host) if not inactive_binding or inactive_binding.host != host: raise n_exc.PortBindingNotFound(port_id=port_id, host=host) network = self.get_network(context, port_db['network_id']) diff --git a/neutron/services/logapi/common/validators.py b/neutron/services/logapi/common/validators.py index 1272d7520c2..24cdde5ad54 100644 --- a/neutron/services/logapi/common/validators.py +++ b/neutron/services/logapi/common/validators.py @@ -96,7 +96,7 @@ def validate_log_type_for_port(log_type, port): log_plugin = directory.get_plugin(alias=plugin_const.LOG_API) drivers = log_plugin.driver_manager.drivers port_binding = utils.get_port_binding_by_status_and_host( - port.binding, constants.ACTIVE, raise_if_not_found=True, + port.bindings, constants.ACTIVE, raise_if_not_found=True, port_id=port['id']) for driver in drivers: vif_type = port_binding.vif_type diff --git a/neutron/services/qos/drivers/manager.py b/neutron/services/qos/drivers/manager.py index c4503b40d80..b6d4d9aee63 100644 --- a/neutron/services/qos/drivers/manager.py +++ b/neutron/services/qos/drivers/manager.py @@ -137,7 +137,7 @@ class QosServiceDriverManager(object): def validate_rule_for_port(self, rule, port): port_binding = utils.get_port_binding_by_status_and_host( - port.binding, lib_constants.ACTIVE, raise_if_not_found=True, + port.bindings, lib_constants.ACTIVE, raise_if_not_found=True, port_id=port['id']) for driver in self._drivers: vif_type = port_binding.vif_type diff --git a/neutron/tests/unit/objects/test_objects.py b/neutron/tests/unit/objects/test_objects.py index b205f818787..926827f48a2 100644 --- a/neutron/tests/unit/objects/test_objects.py +++ b/neutron/tests/unit/objects/test_objects.py @@ -62,7 +62,7 @@ object_data = { 'NetworkPortSecurity': '1.0-b30802391a87945ee9c07582b4ff95e3', 'NetworkRBAC': '1.0-c8a67f39809c5a3c8c7f26f2f2c620b2', 'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8', - 'Port': '1.4-c3937b92962d5b43a09a7de2f44e0ab7', + 'Port': '1.4-1b6183bccfc2cd210919a1a72faefce1', 'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578', 'PortBindingLevel': '1.1-50d47f63218f87581b6cd9a62db574e5', 'PortDataPlaneStatus': '1.0-25be74bda46c749653a10357676c0ab2', diff --git a/neutron/tests/unit/objects/test_ports.py b/neutron/tests/unit/objects/test_ports.py index ef52d849a06..4fe820c0653 100644 --- a/neutron/tests/unit/objects/test_ports.py +++ b/neutron/tests/unit/objects/test_ports.py @@ -446,9 +446,16 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, # Port has no active bindings, so binding attribute should be None self.assertIsNone(port_v1_3['versioned_object.data']['binding']) + # bindings attribute in V1.4 port should have one inactive binding + primitive = port_v1_4.obj_to_primitive() + self.assertEqual(1, + len(primitive['versioned_object.data']['bindings'])) + binding = primitive['versioned_object.data']['bindings'][0] + self.assertEqual(constants.INACTIVE, + binding['versioned_object.data']['status']) + # Port with no binding attribute should be handled without raising # exception - primitive = port_v1_4.obj_to_primitive() - primitive['versioned_object.data'].pop('binding') + primitive['versioned_object.data'].pop('bindings') port_v1_4_no_binding = port_v1_4.obj_from_primitive(primitive) port_v1_4_no_binding.obj_to_primitive(target_version='1.3') diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 9a009a6b5a3..556d897bd74 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -1808,7 +1808,7 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, plugin = directory.get_plugin() binding = utils.get_port_binding_by_status_and_host( plugin._get_port(self.context, - port['port']['id']).port_binding, + port['port']['id']).port_bindings, constants.ACTIVE) binding['host'] = 'test' mech_context = driver_context.PortContext( @@ -1831,7 +1831,7 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, plugin = directory.get_plugin() binding = utils.get_port_binding_by_status_and_host( plugin._get_port(self.context, - port['port']['id']).port_binding, + port['port']['id']).port_bindings, constants.ACTIVE) binding['host'] = 'fake_host' binding['vif_type'] = port_vif_type @@ -1948,7 +1948,7 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, plugin = directory.get_plugin() binding = utils.get_port_binding_by_status_and_host( plugin._get_port(self.context, - port['port']['id']).port_binding, + port['port']['id']).port_bindings, constants.ACTIVE) with self.context.session.begin(subtransactions=True): binding.host = 'test' @@ -1970,7 +1970,7 @@ class TestMl2PortBinding(Ml2PluginV2TestCase, plugin = directory.get_plugin() binding = utils.get_port_binding_by_status_and_host( plugin._get_port(self.context, - port['port']['id']).port_binding, + port['port']['id']).port_bindings, constants.ACTIVE) binding['host'] = 'test' mech_context = driver_context.PortContext( @@ -2959,7 +2959,7 @@ class TestML2Segments(Ml2PluginV2TestCase): with db_api.context_manager.writer.using(self.context): binding = utils.get_port_binding_by_status_and_host( plugin._get_port(self.context, - port['port']['id']).port_binding, + port['port']['id']).port_bindings, constants.ACTIVE) binding['host'] = 'host-ovs-no_filter' mech_context = driver_context.PortContext( diff --git a/neutron/tests/unit/services/logapi/common/test_validators.py b/neutron/tests/unit/services/logapi/common/test_validators.py index dabc93ed5c6..31222537094 100644 --- a/neutron/tests/unit/services/logapi/common/test_validators.py +++ b/neutron/tests/unit/services/logapi/common/test_validators.py @@ -105,7 +105,7 @@ class TestLogDriversLoggingTypeValidations(drv_mgr.TestLogDriversManagerBase): port_binding = ports.PortBinding( self.ctxt, port_id=port_id, vif_type=vif_type, vnic_type=vnic_type) return ports.Port( - self.ctxt, id=uuidutils.generate_uuid(), binding=[port_binding]) + self.ctxt, id=uuidutils.generate_uuid(), bindings=[port_binding]) def _test_validate_log_type_for_port(self, port, expected_result): driver_manager = self._create_manager_with_drivers({ diff --git a/neutron/tests/unit/services/qos/drivers/test_manager.py b/neutron/tests/unit/services/qos/drivers/test_manager.py index 52cf2b7ac9a..6d734bf3bcb 100644 --- a/neutron/tests/unit/services/qos/drivers/test_manager.py +++ b/neutron/tests/unit/services/qos/drivers/test_manager.py @@ -86,7 +86,7 @@ class TestQoSDriversRulesValidations(TestQosDriversManagerBase): port_binding = ports_object.PortBinding( self.ctxt, port_id=port_id, vif_type=vif_type, vnic_type=vnic_type) return ports_object.Port( - self.ctxt, id=uuidutils.generate_uuid(), binding=[port_binding]) + self.ctxt, id=uuidutils.generate_uuid(), bindings=[port_binding]) def _test_validate_rule_for_port(self, port, expected_result): driver_manager = self._create_manager_with_drivers({