Use project_id instead of tenant_id in objects

Objects must use project_id and not tenant_id. The object framework
ensures that tenant_id is added as an extra field for backward
compatibility.

This patch reverts the workaround implemented in change
I4ec9340094bc51cd8aa6e5112bf8114aa26c2982 and implements a proper fix
by explicitly updating the objects.

Co-Authored-By: Artur Korzeniewski <artur.korzeniewski@intel.com>
Co-Authored-By: Darek Smigiel <smigiel.dariusz@gmail.com>

Closes-Bug: #1630748

Change-Id: Iab90bcab41655b2e210aea0e7581eb00b94ce5e5
This commit is contained in:
Henry Gessau 2016-10-18 11:35:24 +02:00 committed by Dariusz Smigiel
parent 1a528e817f
commit 8b048cc287
22 changed files with 102 additions and 41 deletions

View File

@ -74,7 +74,7 @@ class AddressScopeDbMixin(ext_address_scope.AddressScopePluginBase):
"""Create an address scope."""
a_s = address_scope['address_scope']
address_scope_id = a_s.get('id') or uuidutils.generate_uuid()
pool_args = {'tenant_id': a_s['tenant_id'],
pool_args = {'project_id': a_s['tenant_id'],
'id': address_scope_id,
'name': a_s['name'],
'shared': a_s['shared'],

View File

@ -84,11 +84,14 @@ def _check_subnet_not_used(context, subnet_id):
def _update_subnetpool_dict(orig_pool, new_pool):
keys_to_update = (
set(orig_pool.fields.keys()) - set(orig_pool.synthetic_fields))
updated = {k: new_pool.get(k, orig_pool[k]) for k in keys_to_update}
updated = dict((k, v) for k, v in orig_pool.to_dict().items()
if k not in orig_pool.synthetic_fields)
new_prefixes = new_pool.get('prefixes', constants.ATTR_NOT_SPECIFIED)
new_pool = new_pool.copy()
new_prefixes = new_pool.pop('prefixes', constants.ATTR_NOT_SPECIFIED)
for k, v in new_pool.items():
if k not in orig_pool.fields_no_update:
updated[k] = v
if new_prefixes is not constants.ATTR_NOT_SPECIFIED:
orig_ip_set = netaddr.IPSet(orig_pool.prefixes)
new_ip_set = netaddr.IPSet(new_prefixes)
@ -1039,15 +1042,13 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon,
def create_subnetpool(self, context, subnetpool):
sp = subnetpool['subnetpool']
sp_reader = subnet_alloc.SubnetPoolReader(sp)
if sp_reader.address_scope_id is constants.ATTR_NOT_SPECIFIED:
sp_reader.address_scope_id = None
if sp_reader.is_default:
self._check_default_subnetpool_exists(context,
sp_reader.ip_version)
self._validate_address_scope_id(context, sp_reader.address_scope_id,
id, sp_reader.prefixes,
sp_reader.ip_version)
pool_args = {'tenant_id': sp['tenant_id'],
pool_args = {'project_id': sp['tenant_id'],
'id': sp_reader.id,
'name': sp_reader.name,
'ip_version': sp_reader.ip_version,

View File

@ -258,7 +258,7 @@ class SubnetPoolReader(object):
self._read_address_scope(subnetpool)
self.subnetpool = {'id': self.id,
'name': self.name,
'tenant_id': self.tenant_id,
'project_id': self.tenant_id,
'prefixes': self.prefixes,
'min_prefix': self.min_prefix,
'min_prefixlen': self.min_prefixlen,
@ -347,8 +347,11 @@ class SubnetPoolReader(object):
self.prefixes = self._compact_subnetpool_prefix_list(prefix_list)
def _read_address_scope(self, subnetpool):
self.address_scope_id = subnetpool.get('address_scope_id',
constants.ATTR_NOT_SPECIFIED)
address_scope_id = subnetpool.get('address_scope_id',
constants.ATTR_NOT_SPECIFIED)
if address_scope_id is constants.ATTR_NOT_SPECIFIED:
address_scope_id = None
self.address_scope_id = address_scope_id
def _compact_subnetpool_prefix_list(self, prefix_list):
"""Compact any overlapping prefixes in prefix_list and return the

View File

@ -29,7 +29,7 @@ class AddressScope(base.NeutronDbObject):
fields = {
'id': common_types.UUIDField(),
'tenant_id': obj_fields.StringField(nullable=True),
'project_id': obj_fields.StringField(nullable=True),
'name': obj_fields.StringField(),
'shared': obj_fields.BooleanField(),
'ip_version': common_types.IPVersionEnumField(),

View File

@ -25,7 +25,6 @@ from oslo_versionedobjects import fields as obj_fields
import six
from neutron._i18n import _
from neutron.api.v2 import attributes
from neutron.db import api as db_api
from neutron.db import standard_attr
from neutron.objects.db import api as obj_db_api
@ -124,7 +123,6 @@ class NeutronObject(obj_base.VersionedObject,
dict_[field_name].to_dict() if value else None)
else:
dict_[field_name] = field.to_primitive(self, field_name, value)
attributes.populate_project_info(dict_)
return dict_
@classmethod

View File

@ -39,7 +39,8 @@ class QosPolicy(rbac_db.NeutronRbacObject):
# Version 1.1: QosDscpMarkingRule introduced
# Version 1.2: Added QosMinimumBandwidthRule
# Version 1.3: Added standard attributes (created_at, revision, etc)
VERSION = '1.3'
# Version 1.4: Changed tenant_id to project_id
VERSION = '1.4'
# required by RbacNeutronMetaclass
rbac_db_model = QosPolicyRBAC
@ -50,13 +51,13 @@ class QosPolicy(rbac_db.NeutronRbacObject):
fields = {
'id': common_types.UUIDField(),
'tenant_id': obj_fields.StringField(),
'project_id': obj_fields.StringField(),
'name': obj_fields.StringField(),
'shared': obj_fields.BooleanField(default=False),
'rules': obj_fields.ListOfObjectsField('QosRule', subclasses=True),
}
fields_no_update = ['id', 'tenant_id']
fields_no_update = ['id', 'project_id']
synthetic_fields = ['rules']
@ -64,6 +65,9 @@ class QosPolicy(rbac_db.NeutronRbacObject):
'port': port_binding_model}
def obj_load_attr(self, attrname):
if attrname == 'project_id':
return super(QosPolicy, self).obj_load_attr(attrname)
if attrname != 'rules':
raise exceptions.ObjectActionError(
action='obj_load_attr',
@ -235,3 +239,6 @@ class QosPolicy(rbac_db.NeutronRbacObject):
# description was not nullable before
raise exception.IncompatibleObjectVersion(
objver=target_version, objname='QoSPolicy')
if _target_version < (1, 4):
primitive['tenant_id'] = primitive.pop('project_id')

View File

@ -32,7 +32,7 @@ class SubnetPool(base.NeutronDbObject):
fields = {
'id': common_types.UUIDField(),
'tenant_id': obj_fields.StringField(nullable=True),
'project_id': obj_fields.StringField(nullable=True),
'name': obj_fields.StringField(nullable=True),
'ip_version': common_types.IPVersionEnumField(),
'default_prefixlen': common_types.IPNetworkPrefixLenField(),
@ -46,7 +46,7 @@ class SubnetPool(base.NeutronDbObject):
'prefixes': common_types.ListOfIPNetworksField(nullable=True)
}
fields_no_update = ['id', 'tenant_id']
fields_no_update = ['id', 'project_id']
synthetic_fields = ['prefixes']

View File

@ -15,6 +15,7 @@
from neutron_lib import exceptions as n_exc
from oslo_db import exception as o_db_exc
from oslo_utils import versionutils
from oslo_versionedobjects import base as obj_base
from oslo_versionedobjects import fields as obj_fields
@ -84,21 +85,22 @@ class SubPort(base.NeutronDbObject):
@obj_base.VersionedObjectRegistry.register
class Trunk(base.NeutronDbObject):
# Version 1.0: Initial version
VERSION = '1.0'
# Version 1.1: Changed tenant_id to project_id
VERSION = '1.1'
db_model = models.Trunk
fields = {
'admin_state_up': obj_fields.BooleanField(),
'id': common_types.UUIDField(),
'tenant_id': obj_fields.StringField(),
'project_id': obj_fields.StringField(),
'name': obj_fields.StringField(),
'port_id': common_types.UUIDField(),
'status': obj_fields.StringField(),
'sub_ports': obj_fields.ListOfObjectsField(SubPort.__name__),
}
fields_no_update = ['tenant_id', 'port_id']
fields_no_update = ['project_id', 'port_id']
synthetic_fields = ['sub_ports']
@ -123,3 +125,9 @@ class Trunk(base.NeutronDbObject):
def update(self, **kwargs):
self.update_fields(kwargs)
super(Trunk, self).update()
def obj_make_compatible(self, primitive, target_version):
_target_version = versionutils.convert_version_to_tuple(target_version)
if _target_version < (1, 1):
primitive['tenant_id'] = primitive.pop('project_id')

View File

@ -52,6 +52,13 @@ class QoSPlugin(qos.QoSPluginBase):
:returns: a QosPolicy object
"""
# NOTE(dasm): body 'policy' contains both tenant_id and project_id
# but only latter needs to be used to create QosPolicy object.
# We need to remove redundant keyword.
# This cannot be done in other place of stacktrace, because neutron
# needs to be backward compatible.
policy['policy'].pop('tenant_id', None)
policy_obj = policy_object.QosPolicy(context, **policy['policy'])
policy_obj.create()
self.notification_driver_manager.create_policy(context, policy_obj)

View File

@ -219,7 +219,7 @@ class TrunkPlugin(service_base.ServicePluginBase,
id=uuidutils.generate_uuid(),
name=trunk.get('name', ""),
description=trunk_description,
tenant_id=trunk['tenant_id'],
project_id=trunk['tenant_id'],
port_id=trunk['port_id'],
status=constants.DOWN_STATUS,
sub_ports=sub_ports)

View File

@ -84,7 +84,7 @@ class OVSAgentQoSExtensionTestFramework(base.OVSAgentTestFramework):
qos_policy = policy.QosPolicy(
context=None,
tenant_id=uuidutils.generate_uuid(),
project_id=uuidutils.generate_uuid(),
id=policy_id,
name="Test Policy Name",
description="This is a policy for testing purposes",

View File

@ -147,7 +147,7 @@ class LinuxBridgeAgentTests(test_ip_lib.IpLibTestFramework):
def _gen_trunk(self):
trunk_obj = trunk.Trunk(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
tenant_id=uuidutils.generate_uuid())
project_id=uuidutils.generate_uuid())
subports = [trunk.SubPort(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
segmentation_type='vlan',

View File

@ -418,6 +418,13 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
self.assertIn(rule_objs[1], policy_obj_v1_1.rules)
self.assertNotIn(rule_objs[2], policy_obj_v1_1.rules)
def test_v1_4_to_v1_3_drops_project_id(self):
policy_new = self._create_test_policy()
policy_v1_3 = policy_new.obj_to_primitive(target_version='1.3')
self.assertNotIn('project_id', policy_v1_3['versioned_object.data'])
self.assertIn('tenant_id', policy_v1_3['versioned_object.data'])
def test_filter_by_shared(self):
policy_obj = policy.QosPolicy(
self.context, name='shared-policy', shared=True)

View File

@ -28,7 +28,7 @@ from neutron.tests import base as test_base
# alphabetic order.
object_data = {
'_DefaultSecurityGroup': '1.0-971520cb2e0ec06d747885a0cf78347f',
'AddressScope': '1.0-25560799db384acfe1549634959a82b4',
'AddressScope': '1.0-dd0dfdb67775892d3adc090e28e43bd8',
'Agent': '1.0-7106cb40117a8d1f042545796ed8787d',
'AllowedAddressPair': '1.0-9f9186b6f952fbf31d257b0458b852c0',
'DistributedPortBinding': '1.0-39c0d17b281991dcb66716fee5a8bef2',
@ -57,7 +57,7 @@ object_data = {
'QosDscpMarkingRule': '1.2-0313c6554b34fd10c753cb63d638256c',
'QosMinimumBandwidthRule': '1.2-314c3419f4799067cc31cc319080adff',
'QosRuleType': '1.2-e6fd08fcca152c339cbd5e9b94b1b8e7',
'QosPolicy': '1.3-2eb3494f990acae59cb51381e7f99443',
'QosPolicy': '1.4-50460f619c34428ec5651916e938e5a0',
'Route': '1.0-a9883a63b416126f9e345523ec09483b',
'RouterExtraAttributes': '1.0-ef8d61ae2864f0ec9af0ab7939cab318',
'RouterRoute': '1.0-07fc5337c801fb8c6ccfbcc5afb45907',
@ -65,11 +65,11 @@ object_data = {
'SecurityGroupRule': '1.0-e9b8dace9d48b936c62ad40fe1f339d5',
'SegmentHostMapping': '1.0-521597cf82ead26217c3bd10738f00f0',
'Subnet': '1.0-9c19023a61b42d29fbf3766df380e5b7',
'SubnetPool': '1.0-e8300bfbc4762cc88a7f6205b52da2f8',
'SubnetPool': '1.0-a0e03895d1a6e7b9d4ab7b0ca13c3867',
'SubnetPoolPrefix': '1.0-13c15144135eb869faa4a76dc3ee3b6c',
'SubnetServiceType': '1.0-05ae4cdb2a9026a697b143926a1add8c',
'SubPort': '1.0-72c8471068db1f0491b5480fe49b52bb',
'Trunk': '1.0-80ebebb57f2b0dbb510f84d91421ed10',
'Trunk': '1.1-aa3922b39e37fbb89886c2ee8715cf49',
'VlanAllocation': '1.0-72636c1b7d5c8eef987bd09666e64f3e',
'VxlanAllocation': '1.0-934638cd32d00f81d6fbf93c8eb5755a',
'VxlanEndpoint': '1.0-40522eafdcf838758711dfa886cbdb2e',

View File

@ -103,7 +103,7 @@ class TrunkDbObjectTestCase(test_base.BaseDbObjectTestCase,
self.assertRaises(n_exc.PortNotFound, trunk.create)
def _test_create_trunk_with_subports(self, port_id, vids):
tenant_id = uuidutils.generate_uuid()
project_id = uuidutils.generate_uuid()
sub_ports = []
for vid in vids:
@ -112,7 +112,7 @@ class TrunkDbObjectTestCase(test_base.BaseDbObjectTestCase,
segmentation_type='vlan',
segmentation_id=vid))
trunk = t_obj.Trunk(self.context, port_id=port_id,
sub_ports=sub_ports, tenant_id=tenant_id)
sub_ports=sub_ports, project_id=project_id)
trunk.create()
self.assertEqual(sub_ports, trunk.sub_ports)
return trunk
@ -169,3 +169,11 @@ class TrunkDbObjectTestCase(test_base.BaseDbObjectTestCase,
for k in trunk.fields:
if k in kwargs:
self.assertEqual(kwargs[k], trunk[k])
def test_v1_1_to_v1_0_drops_project_id(self):
trunk_new = self._test_create_trunk_with_subports(
self.db_objs[0]['port_id'], [1, 2])
trunk_v1_0 = trunk_new.obj_to_primitive(target_version='1.0')
self.assertNotIn('project_id', trunk_v1_0['versioned_object.data'])
self.assertIn('tenant_id', trunk_v1_0['versioned_object.data'])

View File

@ -73,7 +73,7 @@ class QosSRIOVAgentDriverTestCase(base.BaseTestCase):
def _create_qos_policy_obj(self, rules):
policy_dict = {'id': uuidutils.generate_uuid(),
'tenant_id': uuidutils.generate_uuid(),
'project_id': uuidutils.generate_uuid(),
'name': 'test',
'description': 'test',
'shared': False,

View File

@ -74,7 +74,7 @@ class QosOVSAgentDriverTestCase(ovs_test_base.OVSAgentConfigTestBase):
def _create_qos_policy_obj(self, rules):
policy_dict = {'id': uuidutils.generate_uuid(),
'tenant_id': uuidutils.generate_uuid(),
'project_id': uuidutils.generate_uuid(),
'name': 'test',
'description': 'test',
'shared': False,

View File

@ -43,7 +43,7 @@ class TestQosDriversManagerBase(base.BaseQosTestCase):
driver_mgr_config.register_qos_plugin_opts(config)
self.policy_data = {'policy': {
'id': uuidutils.generate_uuid(),
'tenant_id': uuidutils.generate_uuid(),
'project_id': uuidutils.generate_uuid(),
'name': 'test-policy',
'description': 'test policy description',
'shared': True}}

View File

@ -34,7 +34,7 @@ class TestQosRpcNotificationDriver(base.BaseQosTestCase):
policy_id = uuidutils.generate_uuid()
self.policy_data = {'policy': {
'id': policy_id,
'tenant_id': uuidutils.generate_uuid(),
'project_id': uuidutils.generate_uuid(),
'name': 'testi-policy',
'description': 'test policyi description',
'shared': True}}

View File

@ -9,7 +9,6 @@
# 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 mock
from neutron_lib.plugins import directory
from oslo_config import cfg
@ -60,7 +59,7 @@ class TestQosPlugin(base.BaseQosTestCase):
self.policy_data = {
'policy': {'id': uuidutils.generate_uuid(),
'tenant_id': uuidutils.generate_uuid(),
'project_id': uuidutils.generate_uuid(),
'name': 'test-policy',
'description': 'Test policy description',
'shared': True}}
@ -95,6 +94,28 @@ class TestQosPlugin(base.BaseQosTestCase):
self.qos_plugin.create_policy(self.ctxt, self.policy_data)
self._validate_notif_driver_params('create_policy')
def test_add_policy_with_extra_tenant_keyword(self, *mocks):
policy_id = uuidutils.generate_uuid()
project_id = uuidutils.generate_uuid()
tenant_policy = {
'policy': {'id': policy_id,
'project_id': project_id,
'tenant_id': project_id,
'name': 'test-policy',
'description': 'Test policy description',
'shared': True}}
policy_details = {'id': policy_id,
'project_id': project_id,
'name': 'test-policy',
'description': 'Test policy description',
'shared': True}
with mock.patch('neutron.objects.qos.policy.QosPolicy') as QosMocked:
self.qos_plugin.create_policy(self.ctxt, tenant_policy)
QosMocked.assert_called_once_with(self.ctxt, **policy_details)
@mock.patch(
'neutron.objects.rbac_db.RbacNeutronDbObjectMixin'
'.create_rbac_policy')

View File

@ -17,6 +17,7 @@ import mock
import netaddr
from neutron_lib import constants
from neutron_lib.plugins import directory
from oslo_utils import uuidutils
from neutron import context as nctx
from neutron.db import models_v2
@ -161,7 +162,7 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase):
rev = port['port']['revision_number']
qos_plugin = directory.get_plugin('QOS')
qos_policy = {'policy': {'name': "policy1",
'tenant_id': "tenant1"}}
'project_id': uuidutils.generate_uuid()}}
qos_obj = qos_plugin.create_policy(self.ctx, qos_policy)
data = {'port': {'qos_policy_id': qos_obj['id']}}
response = self._update('ports', port['port']['id'], data)
@ -173,7 +174,7 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase):
rev = network['network']['revision_number']
qos_plugin = directory.get_plugin('QOS')
qos_policy = {'policy': {'name': "policy1",
'tenant_id': "tenant1"}}
'project_id': uuidutils.generate_uuid()}}
qos_obj = qos_plugin.create_policy(self.ctx, qos_policy)
data = {'network': {'qos_policy_id': qos_obj['id']}}
response = self._update('networks', network['network']['id'], data)

View File

@ -35,7 +35,7 @@ class LinuxBridgeTrunkDriverTestCase(base.BaseTestCase):
self.lbd = driver.LinuxBridgeTrunkDriver(self.plumber, self.tapi)
self.trunk = trunk.Trunk(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
tenant_id=uuidutils.generate_uuid())
project_id=uuidutils.generate_uuid())
self.subports = [trunk.SubPort(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
segmentation_type='vlan',
@ -150,7 +150,7 @@ class TrunkAPITestCase(base.BaseTestCase):
self.tapi = driver._TrunkAPI(self.stub)
self.trunk = trunk.Trunk(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
tenant_id=uuidutils.generate_uuid())
project_id=uuidutils.generate_uuid())
self.subports = [trunk.SubPort(id=uuidutils.generate_uuid(),
port_id=uuidutils.generate_uuid(),
segmentation_type='vlan',